1.vue2中的响应式与vue3中有什么不同
vue2中响应式采用Object.defineProperty
对对象中的属性进行get
和set
拦截。创建observer
类,为每个数据创建一个数组来管理依赖,在getter
中收集依赖,在setter
中通知依赖更新。所以每当属性进行读写操作时就会触发get
和set
,从而实现对属性的监听。
vue2中对对象属性的访问需要先知道特定的key
,所以对于对象中新增的属性、数组中通过下标新增数据会有些不足。
vue2中的全局的$set
方法的本质就是给新增的属性手动observer
Object.defineProperty(car, 'price', {
get() {},
set() {}
})
vue3中的响应式则是借助
Proxy
,target
是目标对象可以是数组甚至是另一个代理,handler
通常是用来定制拦截行为,通常含有 has
、get
、set
、deleteProperty
等方法。可以看到vue3对对象的代理不依赖对象属性,所以可以很好的解决vue2中的不足。const proxy = new Proxy(target, {
get: function(target, propKey, receiver) {
return '10'
}
})
2.vue3比vue2优化了哪些地方
- 全局API的修改:vue2中是导出全局的vue对象,在单元测试中,很容易污染全局环境以及带来冲突。vue3中通过
createApp
创建app实例,一切操作修改从直接操作Vue全局对象,转变成了操作vue实例 - 一些全局的api支持了
tree-shaking
,变成了具名的导出,从vue对象中脱离。如nextTick的引用方式从Vue.nextTicke
变成了import {nextTick, observable} from vue
- 通过
Composition API
以逻辑来划分代码,更好的重用代码,vue2中对代码的抽离可以通过mixins
,但是mixins
存在命名冲突、暴露出来的变量来源不清晰等问题。composition api
可以进行重命名,避免了命名冲突。 - 对typescript更好的支持
- 新增了一些其他的特性,比如
teleport
和suspense
defineAsyncCompoent
方法,方法接受返回promise
的工厂函数,动态加载组件const AsyncComp = defineAsyncComopent(
() => new Promise((resolve, reject) => {
resolve({
template: 'test'
})
})
)
vue2中则是直接通过import导入。
4.vue3中的teleport组件
teleport
像是一个传送门,允许我们控制在哪个dom节点下呈现html。to
属性接受一个querySelector,设置父级节点。实现原理:通过
createBlock
生成一个vnode
,创建teleport
组件,通过调用Teleport.process
,选中父节点,mountChildren
方法挂在到dom
中。
5.说说虚拟dom及vue3中对虚拟dom对优化 虚拟dom就是一个js对象来描述dom节点,当数据发生变化时,对比变化前后的虚拟dom节点,通过dom-diff算法计算出需要更新的地方,然后来更新需要的视图。
vue中通过
VNode
类来实例化出不同类型的虚拟dom,比如注释节点通过isComment来表示是否是注释节点,text表示具体的注释信息。export const createEmptyVNode = (text: string = '') => {
const node = new VNode();
node.text = text;
node.isComment = true;
return node;
}
优化前,在一个默认的Virtual Dom的diff中,需要遍历所有节点,去比较旧的props和新的props有没有变化
【vue3面试知识点十大问】而优化之后,创建的vnode多了
patch flag
标记该节点的可变属性,当 diff 算法走到 _createBlock 函数的时候,会忽略所有的静态节点,只对有标记的动态节点进行对比,而且在多层的嵌套下依然有效。6.vue3中的生命周期
文章图片
beforeCreate和create几乎是同时在setup函数中进行触发的。生命周期函数的书写OnBeforeMount、OnMounted、onUpdated
vue3中多了两个调试钩子函数onRenderTracked onRenderTriggered,顾名思义就是在render重新绘制时进行触
7.vue中的key有什么作用
- 在
dom-diff
中标识Vnode
,标识变化前后是否是同一个组件 - 通过
key
复用元素,所以修改某一个元素的key可以重新渲染该元素
- vue3 中的
watch
函数第一个参数为响应式对象、有getter/setter
的effect
函数、或者这些类型数组;第二个参数为数据变化时的回调;第三个参数为watchOption
,提供是否立即监听和是否深度监听的配置。 - vue3 可以多次使用
watch
方法
watch(data, () => {}) watch(() => data.name, () => {}) watch([data, name], () => {})
- vue3 的 setup 中不存在
this
对象,监听路由需要使用 vue-router 提供的userRoute
,vue2 则是在 watch 对象里添加'$route'
进行监听
import { useRoute } from "vue-router"; // setup const route = useRoute(); const userData = https://www.it610.com/article/ref(); // 当参数更改时获取用户信息 watch(() => route.params, () => {});
watchEffect
立即执行传入的函数,在初始化时自动收集依赖,并在其依赖变更时重新运行该函数watchEffect
无法获取原值,只能得到变化后的值
StopHandle.stop()
函数手动停止监听const stopHandle = watchEffect();
handle.stop();
10.v-model的原理及vue3中v-model的改变
v-model
通过在数据修改时,通知父级节点实现数据的双向绑定。其实是一个语法糖当满足以下两个条件时,可实现自定义组件的v-model:- 子组件受控接收prop
- 数据修改时触发event把新的数据提交给父组件
props: {
value: String
},
model: {
prop: 'value',
event: 'change'
}
vue3中升级了v-mode的用法,通过
update:modelValue
来触发事件,prop也被更改为modelValue
。还在一个组件上支持多个v-model,如新增v-model:lastName
等。props: {
modelValue: String,
}
emits: ['update:modelValue'],
methods: {
changeTitle() {
this.$emit('update:modelValue', title)
}
}
参考链接
- 抄笔记:尤雨溪在Vue3.0 Beta直播里聊到了这些
- Vue原理解析(八):一起搞明白令人头疼的diff算法