一、vue的生命周期
这里主要讲解一下vue的生命周期、vue在生命周期帮助我们做了什么、在此生命周期我们可以做什么。
beforeCreate是new Vue()之后触发的第一个钩子,此时data、methods、computed以及watch上的数据和方法还未初始化,不能被访问。
created在实例创建完成后发生,当前阶段已经完成数据观测,在这里可以使用数据、更改数据,不会触发updated函数。
- 可以做什么
- data和methods的数据和方法已经完成初始化,可以操作data中的数据,使用methods里面的方法,最早可以从这个阶段进行。
- 在此阶段无法与DOM进行交互,如果非要,可以使用vm.$nextTick来访问DOM。
- 异步数据请求适合在created钩子中使用,比如数据初始化。
beforeMount发生在挂载之前,在此之前template模版已导入渲染函数编译。而当前阶段虚拟DOM已经创建完成,即将开始渲染。在此时可以对数据进行更改,不会触发updated。
mounted在挂载完成后发生,此时真实的DOM已经挂载完毕,数据完成双向绑定,可以访问到DOM节点,使用$refs对DOM进行操作。
beforeUpdate发生在更新之前,也就是响应式数据发生更新,虚拟DOM重新渲染之前被触发,在当前阶段更改数据,不会造成重渲染。
updated发生在更新完成后,当前阶段组件DOM已经完成更新。需要避免在此阶段改变数据,因为会导致无限循环更新。
beforeDestroy发生在实例销毁之前,此阶段实例完全可以被使用,在此时进行善后收尾工作,比如:清除定时器。
destroyed发生在实例销毁之后,此时只剩下dom空壳。组件已被拆解,数据绑定被卸除,监听被移除,子实例也统统被销毁。
二、vue响应式原理是什么?vue3有何不同?
vue在初始化数据时,使用Object.defineProperty重新定义data中的所有属性,当页面使用对应属性时,首先会进行依赖收集,当对应属性发生变化时,会通知相关依赖进行更新操作。(发布订阅)
vue3使用Proxy来代替Object.defineProperty。因为Proxy可以监听对象和数组的变化,并且有多达13种拦截方式。并且作为新标准将受到浏览器厂商重点持续的性能优化。
三、vue2与vue3的区别
- vue3采用TS编写源码。
- vue3采用组合式(composition) API,vue2采用选项式(options)API。
- 响应式原理不同。vue3采用Proxy,vue2采用Object.defineProperty。
- vue3的template模版支持多个根标签。
- vue3采用了setup代替了beforeCreate和created。
四、MVVM的理解
MVVM指Model- View- ViewModel模型。其中Model代表数据模型,View代表UI视图,ViewModel是数据和视图的桥梁。数据变化会绑定到ViewModel上来驱动视图更新,视图变化会通知ViewModel来更新数据。
五、v-model双向绑定的原理
v-model是一个语法糖,可以看成value+input方法的语法糖。
六、vue组件通信方式
- 父传子
props,子传父$on、$emit - 获取父子组件实例
$parent、$children Ref获取组件实例上的属性和方法- 依赖注入 祖孙组件通信
Provide、inject vuex
七、vue路由实现,hash路由和history路由
hash路由路径中会多一个#
八、v-if和v-show的区别
v-if: 在js层面处理,如果为false,则会销毁元素。
v-show: 在css层面处理,如果为false,则会设置元素display:none。
九、keep-alive作用
keep-alive可以实现组件缓存,当组件切换时,不会销毁当前组件。
十、nextTick的作用
在下一次DOM更新循环结束之后延迟调用。
十一、Vue SSR实现原理
SSR指服务端渲染,使用服务端去请求数据,返回html给客户端。
SSR有利于SEO优化,首屏加载优化等。
十二、Vue中data为什么是函数
一个组件被复用多次的话,也就会创建多个实例。如果是data是对象的话,多次调用会相互影响。data是函数,多次调用,每次都会返回一个新的对象。
十三、Vue与React的区别
Vue双向数据绑定,React单向数据流。
十四、Vue修饰符有哪些
在Vue中修饰符可分为3类: 1. 事件修饰符 2. 按键修饰符 3. 表单修饰符
事件修饰符
.stop:阻止冒泡。.prevent:阻止默认事件。.capture:使用事件捕获模式。.self:只在当前元素本身触发。.once:只触发一次。.passive:默认行为将会立刻触发。
按键修饰符
.left:左键.right:右键.middle:滚轮.enter:回车.tab:制表键.delete:捕获"删除"和"退格".esc:返回.space:空格.up:上.down:下.left:左.right: 右.ctrl:ctrl键.alt:alt键.shift:shift键.meta:meta键
表单修饰符
.lazy:在文本框失去焦点时渲染.number:将文本框的内容全部转化成Number类型.trim:可以自动过滤输入首尾的空格
十五、如何在vue项目实现性能优化
编码阶段
- 避免重复多次的修改data中的属性
- v-if和v-for不能连用
- 使用key保证唯一
- 防抖、节流
- 图片懒加载
- 第三方模块按需导入
SEO优化
- 使用服务端渲染SSR
打包优化
- 压缩代码
- Tree Sharking
- 使用cdn加载第三方模块
用户体验
- 骨架屏
- PWA
十六、Vue中key的作用
key保证唯一,可以高效的更新虚拟DOM。
十七、vue2.x和vue3.x的diff算法
diff算法有以下过程:
- 同级比较,在比较子节点
- 先判断一方有子节点一方没有子节点的情况(如果旧的有子节点,新的没有子节点,直接将旧的移除;如果旧的没有子节点,新的有子节点,直接创建)
- 比较都有子节点的情况(核心diff)
- 递归比较子节点
Vue2核心diff采用了双端比较算法。
Vue3核心diff借鉴了ivi算法和inferno算法。
十八、组件中name的作用
可以通过名字找到对应组件
十九、ref的作用
- 可以获取组件实例
- 可以获取DOM元素
二十、接口请求一般放在哪个生命周期
接口请求可以放在created、beforeMount、mounted三个钩子函数中,因为在这三个钩子函数中,data已经创建,可以将服务端返回的数据赋值。
推荐使用created钩子调用异步请求。
二十一、computed和watch的作用和区别
- computed有缓存,依赖值发生变化才会更新,watch没有
- watch支持异步,computed不支持
二十二、修改element- ui 的组件样式,是否需要深度监听
不一定。比如el-input组件,如果修改根节点,vue会把scoped的data-v属性透传到子组件根节点, 可以直接通过class或者.el-input覆盖样式。
但是如果需要修改组件内部的DOM,比如el-input_wrapper或.el-input_inner,这些内部DOM没有data-v属性,必须使用deep.
为什么组件根节点可以命中scoped样式
Vue会把data-v-hash自动透传到组件根节点。 假设组件
<template>
<el-input class="my-input" />
</template>
<style scoped>
.my-input {
border: 1px solid red;
}
.el-input {
width: 300px;
}
</style>
可以透传(不需要deep):
// vue编译后
<div class="el-input my-input" data-v-123>
// data-v-123 会透传到子组件的根节点
.my-input[data-v-123] {
border: 1px solid red;
}
.el-input[data-v-123] {
width: 300px;
}
不可以透传的情况(必须使用deep),el-input的真实结构:
<div class="el-input">
<div class="el-input__wrapper">
<input class="el-input__inner">
</div>
</div>
.el-input__inner {
border: none;
}
// vue编译后,匹配不到
.el-input__inner[data-v-123]
为什么有的时候.el-input修改不了
- 修改错了DOM,比如修改
el-input的边框其实在el-input_warapper上; - 组件库的样式权重更高,导致覆盖失败;
- 在
scoped样式下,内部DOM没有data-v属性,需要使用:deep穿透