vue复习

您所在的位置:网站首页 axios多个请求防止触发多次弹窗 vue复习

vue复习

2023-04-29 10:53| 来源: 网络整理| 查看: 265

总结题 VUE

ref :是 元素的属性,用于设置在元素上

$refs :是 ref 的集合,集合里面包含了当前.vue中的所有 ref

用于获取普通元素中的 DOM 以及 子组件中方法/参数的

$el :是 用于获取组件内 DOM(包括子组件,当前.vue组件,以及父组件)

vue中扩展组件 1、mixin 一个组件引入了mixin,mixin里面生命周期和组件内的生命周期哪个先执行, data会不会覆盖, 方法同名会不会覆盖

mixin生命周期总在组件生命周期之前执行 image.png mixin里面可以写data,methods,computed mixins中的data会合并到data中,有冲突的话,data中数据覆盖mixins中的数据。

同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用 例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。

2、slot

插槽主要用于vue组件中的内容分发,也可以用于组件扩展。

子组件Child

匿名插槽

这个内容会被父组件传递的内容替换 复制代码 复制代码

父组件Parent

(父组件传递的内容) // 可以传组件 复制代码 复制代码

如果要精确分发到不同位置可以使用具名插槽,如果要使用子组件中的数据可以使用作用域插槽。

具名插槽

复制代码 Here might be a page title - 注意:一个不带 name 的 出口会带有隐含的名字“default”。 A paragraph for the main content. And another one. Here might be a page title A paragraph for the main content. And another one. 复制代码

作用域插槽

Vue.js中的作用域插槽是一种特殊类型的插槽,用作一个(能被传递数据的)可重用模板,来代替已经渲染好的元素。作用域插槽其实就是带数据的插槽,即带参数的插槽,简单的来说就是子组件提供给父组件的参数,该参数仅限于插槽中使用,父组件可根据子组件传过来的插槽数据来进行不同的方式展现和填充插槽内容¹。

以下是Vue.js中作用域插槽的示例代码:

后备内容 // 后备内容什么是后备内容呢,一个slot有它的默认的内容, 有时为一个插槽设置具体的后备 (也就是默认的) 内容是很有用的, 它只会在没有提供内容的时候被渲染。 //slotProps可以随便命名 {{ slotProps.data }} 复制代码

跟其他不同,是由子组件传值给父组件展示,数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定,也就是说,作用域插槽的不同之处就在于,数据不在父组件身上,而是在子组件身上,且组件的结构和内容由父组件决定。作用域组件限定了组件内结构和数据的展示范围,以便在开发中我们可以根据一个组件而不断变换其中的内容和结构。

3、extend

使用基础Vue构造器,创建一个"子类"。参数是一个包含组件选项的对象。 就是把一个组件通过Vue.extend创造一个子类,然后再通过.$mount()来挂载, extend提供了一个能够构造组件的函数(也就是构造器)。在一些特定的应用场景(如自己构建一个复杂弹窗)下,我们使用这种函数式的构造组件的方法,会更灵活一些。 将dom插入body

document.body.appendChild(demo.$el);

以下是一个使用Vue.extend的例子:¹ ```javascript // 创建构造器 var Profile = Vue.extend({ template: '

{{firstName}} {{lastName}} aka {{alias}}

', data: function () { return { firstName: 'Walter', lastName: 'White', alias: 'Heisenberg' } } }) // 创建 Profile 实例,并挂载到一个元素上。 new Profile().$mount('#mount-point') 复制代码

vue3中被移除 使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。 类似,this.$message.info('xxx')就是通过这种方法创造的组件实例,再讲这个组件传到了body上,

vue.install

在 Vue.js 中,install 方法是插件的一个方法,用于定义 Vue.js 插件。当使用 Vue.use() 安装插件时,会调用插件的 install 方法。在 install 方法中,我们可以定义全局组件、指令、混入等,并将它们挂载到 Vue 的原型上,以便在其他组件中使用。

以下是一个 Vue.js 插件的 install 方法示例代码,其中第二个参数是可选的选项对象,用于传递插件的配置信息。在 install 方法中,我们可以使用这个选项对象来配置插件的行为。例如,我们可以定义一个名为 prefix 的选项,用于指定全局组件名的前缀。

export default { install(Vue, options) { // 使用 options 配置插件 const prefix = options && options.prefix ? options.prefix : '' // 全局注册组件 Vue.component(`${prefix}my-component`, { // ... }) // 全局注册指令 Vue.directive(`${prefix}my-directive`, { // ... }) // 全局注册混入 Vue.mixin({ // ... }) // 挂载到 Vue 原型上 Vue.prototype.$myMethod = function (methodOptions) { // ... } } } 复制代码 父子组件的生命周期执行顺序

image.png

watch的执行顺序

如果不设置 immediate: true,watch在beforeUpdate 之后执行,如果设置了immediate属性,在beforeCreate后执行 props,methods,data以及computed的初始化都是在beforeCreated和created之间完成的 computed数据的执行是在beforeMount和mounted之间

讲讲生命周期方法有哪些,对应哪个阶段 什么阶段能发起请求

可以在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。

但是推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点: 能更快获取到服务端数据,减少页面loading 时间; ssr不支持 beforeMount 、mounted 钩子函数,所以放在 created 中有助于一致性;

beforeCreate 在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。在当前阶段 data、methods、computed 以及 watch 上的数据和方法都不能被访问

created 实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。这里没有el(ref),如果非要想与Dom进行交互,可以通过vm.el(ref),如果非要想与 Dom 进行交互,可以通过 vm.el(ref),如果非要想与Dom进行交互,可以通过vm.nextTick 来访问 Dom

beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用。最后一次更改数据的机会

mounted 在挂载完成后发生,在当前阶段,真实的 Dom 挂载完毕,数据完成双向绑定,可以访问到 Dom 节点

beforeUpdate 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁(patch)之前。可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程

updated 发生在更新完成之后,当前阶段组件 Dom 已完成更新。要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新,该钩子在服务器端渲染期间不被调用。

beforeDestroy 实例销毁之前调用。在这一步,实例仍然完全可用。我们可以在这时进行善后收尾工作,比如清除计时器。

destroyed Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。

activated keep-alive 专属,组件被激活时调用

deactivated keep-alive 专属,组件被销毁时调用

vue生命周期执行顺序

执行顺序是:created中的同步任务–mounted中的同步任务–created中的异步任务–mounted中的同步任务

只是比较他们的执行顺序的话,不用考虑太多created与mounted,他们可以理解为将created与mounted放在一起,只是created放在上面,mounted放下面的代码顺序,然后按正常执行顺序执行

只要同步任务执行完了,引擎就会去检查那些挂起来的异步任务,是不是可以进入主线程了。这种循环检查的机制,就叫做事件循环(Event Loop)。

前端解决跨域

待补充

虚拟DOM

待补充 可以实现组件缓存,当组件切换时不会对当前组件进行卸载

用一个原生的 JS 对象去描述一个 DOM 节点,是对真实 DOM 的一层抽象。

watch 和computed区别

watch和computed都是以Vue的依赖追踪机制为基础 watch处理的场景是:一个数据影响多个数据 computed处理场景是:一个数据受多个数据影响 在computed中定义的每一个计算属性,都会被缓存起来,只有当计算属性里面依赖的一个或多个属性变化了,才会重新计算当前计算属性的值。

token

获取token的方式,插件cookie-util,或者document.cookie 循环,再截取=号

vue组件通讯方式

根据组件之间关系讨论组件通信

父子组件

props/$emit/$parent/ref/$attrs

兄弟组件

$parent/$root/eventbus/vuex

跨层级关系

eventbus/vuex/provide+inject

props,$parent/$children,attrs/listeners,provide/inject,$refs,EventBus中央事件,vuex,emit,on

props

props: { msg: { type: String, default: "", }, } props也可以设置默认值,和类型

sync父子组件双向绑定,子组件可以修改父组件数据

props传值的时候,加上.sync

复制代码

然后子组件 this.$emit('update:demo','demo111')

v-model双向绑定 v-model是语法糖,默认情况下相当于:value和@input。使用v-model可以减少大量繁琐的事件处理代码,提高开发效率。 父组件传值 image.png 子组件接收,修改值 image.png

子组件里面的model的prop可以重新命名双向绑定的值,model里面的event可以修改emit调用方法名

.sync 和 v-model 的区别

先上结论:两者的本质都是语法糖,目的都是实现组件与外部数据的双向绑定。v-model 是 .sync的一种体现。.sync 比较灵活;v-model较单一

v-model只能有一个,(一个组件只有一个model)

个人理解,别的就是语义的区别了,prop.sync表示这个子组件会修改父组件的值,v-model表示这是个表单类型的组件。

v-model一般是表单组件,绑定的是value属性,这个值的双向绑定也不是父组件和子组件的关系,而是view和model的对应关系,因为表单组件的值的变化来自于用户输入

而sync是指父子组件之间的通信

EventBus

EventBus 是中央事件总线,不管是父子组件,兄弟组件,跨层级组件等都可以使用它完成通信操作

定义方式有三种

// 方法一 // 抽离成一个单独的 js 文件 Bus.js ,然后在需要的地方引入 // Bus.js import Vue from "vue" export default new Vue() // 方法二 直接挂载到全局 // main.js import Vue from "vue" Vue.prototype.$bus = new Vue() // 方法三 注入到 Vue 根对象上 // main.js import Vue from "vue" new Vue({ el:"#app", data:{ Bus: new Vue() } }) 复制代码 复制代码

使用如下,以方法一按需引入为例

// 在需要向外部发送自定义事件的组件内 按钮 import Bus from "./Bus.js" export default{ methods:{ handlerClick(){ // 自定义事件名 sendMsg Bus.$emit("sendMsg", "这是要向外部发送的数据") } } } // 在需要接收外部事件的组件内 import Bus from "./Bus.js" export default{ mounted(){ // 监听事件的触发 Bus.$on("sendMsg", data => { console.log("这是接收到的数据:", data) }) }, beforeDestroy(){ // 取消监听 Bus.$off("sendMsg") } } 复制代码 attrs

当父组件传递了很多数据给子组件时,子组件没有声明props来进行接收,那么子组件中的attrs属性就包含了所有父组件传来的数据(除开已经props声明了的),子组件还可以使用v−bind="attrs"的形式向它的子组件(孙子组件)传递数据,孙子组件使用$attrs的方式和它的父组件原理类似。

比如给子组件传了什么数据,但是子组件props 只写了msg, this.$attrs就包含了其他了msg1,msg2,msg3这些没接手的 子组件也可以给它的子组件传值,通过v-bind="$attrs"的方法, $attrs就是父组件传来的值(除开已经props声明了的) 复制代码 $listeners

当父组件在子组件上定义了一些自定义的非原生事件时(就是@绑定的事件),在子组件内部可以通过$listeners属性获取到这些自定义事件。*

$root

可以访问app.vue里面的数据和方法

slot

就是把子组件的数据通过插槽的方式传给父组件使用,然后再插回来 // Child.vue

export default{ data(){ return { user:{ name:"沐华" } } } } // Parent.vue {{ slotProps.user.name }} 复制代码 provide inject // 父组件 provide: { foo: 'bar' // 可以是函数 } // 子组件 inject: { foo: { default() { return 'baz' } }, changeReport: { default: () => { return () => { } // 返回默认函数,如果父组件没有传对应,而子组件又调用了,并且传参了,默认值不是函数会报错 }, treatDefaultAsFactory: false }, } 复制代码 keep-alive

两个生命周期 activated/deactivated,用来得知当前组件是否处于活跃状态。

当引入keep-alive的时候,页面第一次进入,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated

keep-alive 提供了include和exclude两个属性,允许组件有条件的缓存

实现原理是在created的时候,将需要缓存的vnode节点放到cache中,在render时根据name再进行取出

注意 vue不建议过多使用 refs 属性

ref属性是把子组件的实例拿到父组件里面来操作,这在一定程度上破坏了组件逻辑分离的原则,强化了组件之间的耦合度

如果你要向子组件传递数据,应该直接使用props或者Vuex、Pinia这类状态管理插件

如果是要传递事件,应该是用事件总线eventbus机制,或者自定义一些小型的发布-订阅管理机制

只要父子组件是在你自己的控制范围内的,绝大多数情况下都不应该使用ref来完成业务

一般不得不使用ref的地方常见于调用第三方的组件库,对方没有暴露某些内部逻辑的接口,但由于业务需求必须要使用这些逻辑,这时候就只能通过ref拿到子组件实例然后强行调用子组件内部的函数了

虽然短时间内可以快速完成业务逻辑,然而弊端是显而易见的,因为很可能这些内部函数在某次组件库升级更新后就弃用了,或者改变了名字,参数等等,这时候你的程序就会直接报错甚至崩溃了

你使用ref的地方越多,将来需要维护的地方也就越多,你的程序潜在崩溃风险就越大

hook

this.$on一个自定义事件,this.$once一个自定义事件,但是只触发一次 vue2中有hook的概念

created() { this.a // 执行一大堆的其他操作 }, mounted() { this.b // 执行一大堆的其他操作 } 复制代码

可以写成,更加简洁,也可以用来清除定时器,监听

created() { this.a // 执行一大堆的其他操作 this.$once((hook:mounted),()=>{ this.b }) }, 复制代码 @hook绑定

再来说第二种场景吧,假如你用了第三方的 组件,想在第三方组件数据变化时进行一些操作,而这个组件正好没有提供change方法 这时候应该怎么办?当然最好是可以深入组件去修改。但是假如第三方组件又是打包过后的代码呢?痛苦的去看么?

import XxxComp from '../components/xxx-comp' export default { components: { XxxComp }, methods: { handleUpdateChange () { console.log('组件的updated钩子函数被触发') } } } 复制代码 v-if和v-for

在vue2中,v-for大于v-if,每次重新渲染会遍历整个数组,很费时间,而vue3中 v-if大于v-for,当v-if执行时,v-for还没生成会直接报错,永远不要把v-if和v-for放在同一层,可以分层放

vue优化

待补充

对象层级不要过深,否则性能就会差

不需要响应式的数据不要放到 data 中(可以用 Object.freeze() 冻结数据)

Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;

冻结了一个对象则不能向这个对象添加新的属性 不能删除已有属性 不能修改该对象已有属性的可枚举性、可配置性、可写性, 以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改 freeze() 返回和传入的参数相同的对象

使用

const demo = {a:1} Object.freeze(demo),数组一样,Object.freeze只能进行浅冻结,如果对象里面有对象的情况下则无法冻结,需要递归,深度冻结 模拟Object.freeze原理主要用到了2个方法, Object.definedProperty()、Object.seal() Object.definedProperty方法可以定义对象属性的特性 Object.seal 可以让对象不能被扩展

v-if 和 v-show 区分使用场景

computed 和 watch 区分使用场景

v-for 遍历必须加 key,key 最好是 id 值,且避免同时使用 v-if

大数据列表和表格性能优化-虚拟列表/虚拟表格

防止内部泄漏,组件销毁后把全局变量和事件销毁

图片懒加载

路由懒加载

第三方插件的按需引入

适当采用 keep-alive 缓存组件

防抖、节流运用

图片懒加载

img标签会在html渲染解析到的时候,如果解析到img src值,则浏览器会立即开启一个线程去请求该资源。 正常情况是解析到了src便发起请求

可视化的时候再渲染图片 document.documentElement.clientHeight//获取屏幕可视区域的高度 document.documentElement.scrollTop//获取浏览器窗口顶部与文档顶部之间的距离,也就是滚动条滚动的距离 element.offsetTop//获取元素相对于文档顶部的高度

图片过大加载慢时候

如果是相册之类的可以预加载,在展示当前图片的时候,就加载它的前一个和后一个图片 加载的时候可以先加载一个压缩率非常高的缩略图,以提高用户体验,点击再或加载到之后再查看清晰图 使用渐进式jpeg,会提高用户体验 echarts不均匀刻度

一、修改纵坐标的数值,formatter二、处理原数据,采用的方法是把以前100以内的数据模拟到6000以内,就是同比例放大。

修饰符 .stop 阻止事件继续传播 .prevent 阻止标签默认行为 .capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理 .self 只当在 event.target 是当前元素自身时触发处理函数 .once 事件将只会触发一次 .passive 告诉浏览器你不想阻止事件的默认行为 .lazy 通过这个修饰符,转变为在 change 事件再同步 .number 自动将用户的输入值转化为数值类型 .trim 自动过滤用户输入的首尾空格 vue数组视图更新

vue数组更新方法 push,shift,pop,splice,unshift,sort,reverse 如果不修改数组触发视图刷新 this.demo = [...this.demo] this.demo = this.demo.concat() 原理其实也是push

VUE框架理解 axios get

000000 调用型

`axios.get('url', { params: { id: 'aaa' } }).then(res => { console.log(res) })` 复制代码

axios型

axios({ method: 'get', url: 'url', params: { id: '111' } }).then(res => { console.log(res) }) 复制代码 post

调用型

`axios.post('url', data).then(res => { console.log(res) })` 复制代码

axios型

axios({ method: 'get', url: 'url', data:'data' }).then(res => { console.log(res) }) 复制代码 delete //直接从url里面删除 axios.delete('url',{ params:{ id:12 } }).then((res)=>{ console.log(res) }) 复制代码

axios型

axios.delete('url',{data:'data'}).then((res)=>{ console.log(res) }) 复制代码 实例

因为会用到不同的后端域名,直接调用axios,域名会是loacal:8080,所以我们要创建不同实例,全局配置 axios.defaults.timeout = 1000 注意 请求配置 > 实例配置 > 全局配置

let instance = axios.create({         baseURL:'http://localhost:8080',//基本请求路径  baseURL,可以通过window.g 或者process.env来拿 timeout:1000,//超时设定}) 复制代码 请求拦截,响应拦截 // 请求拦截 axiosInstance.interceptors.request.use( config => { // 让每个请求携带自定义token let token = '' const cookie = document.cookie.split('; ') for (let i = 0; i < cookie.length; i++) { const arr = cookie[i].split('=') if (arr[0] === 'token-oe') { token = arr[1] } } if (token) config.headers.Authorization = token return config }, err => { return Promise.reject(err) } ) // 响应拦截 axiosInstance.interceptors.response.use(response => { const { status, message } = response.data // 获取状态码,可以处理token失效之类的问题 return new Promise((resolve, reject) => { if (status === 200) { resolve(response.data) } else if (status === 400) { // 清除cookie // cookieUtil.removeToken() router.push({ path: '/login' }) } else { console.log(message) reject(response.data) } }) } 复制代码


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3