如果用过 vue3,或者面试的工作要求会 vue3,在面试的时候大概率会问到这个问题,接下来我们由浅入深的来总结一下
本文仅用于面试时回答问题,某些具体实现以后可以在另外的文章中写些代码再分享
一、表面用法区别
-
语法
vue2 是 options API,data、watch、computed、methods、mixins 等定义都集中在组件中
vue3 虽然也支持 vue2 的写法,但是主推 composition API,组件中定 setup 函数,定义响应式变量用 ref、reactive 语法,computed、watch和各生命周期函数都直接从 vue 中引入
-
公共逻辑抽取
vue2中各个变量相关的定义和操作逻辑都分散在不同的位置,如果要抽取公共的组件逻辑,是用 mixin 的方式引入
vue3完全颗粒化了,各个生命周期函数都可以多次使用,代码中跟某些变量相关的代码可以被整体封装了,能准确知道来源
二、实现原理进步与优化
-
响应式
vue2中的响应式是 Object.defineProperty 去拦截对象操作,但新增和删除属性需要使用 delete 语法,针对数组的操作只能使用 push、pop、splice、shift、unshift、sort 等方法操作
vue3中使用 es6 的 Proxy,针对对象和数组的绝大多数操作可以原生响应了,但是 Proxy 只能在现代浏览器中使用,老的 IE 等浏览器会有兼容性问题
-
nextTick
针对 nextTick 其实是参考的浏览器的事件循环机制,所有的修改数据操作在 dom 变更处理完成之后会调用 nextTick 函数传进来的回调函数
具体实现方式在 vue3 中就是 Promise 异步回调,因为 vue3 是面向现代浏览器的,而在现代浏览器中已经全都有 Promise 了,所以,如果问到这个问题,最好回答 vue2 中的实现,基于是否支持在以下方式中逐步降级:
Promise
MessageChannel
setImmediate
setTimeout
-
静态节点缓存
vue3 中的节点标记做的很丰富,总共有 13 种标记,针对静态节点做了缓存,以空间换时间的方式提升了响应速度
-
按需 diff
vue3 中的响应式变量和 vnode 之间是有映射关系的,并且像 watch 等函数跟响应式变量之间也是有映射关系的,具体实现是用的 es6 中的 WeakMap,当变量被回收,WeakMap 中存储的数据自然清除
-
多实例支持
vue2 中要实现多实例会有些麻烦,因为有些插件会修改 Vue 原型,导致多实例会被原型污染
vue3 因为是工厂模式,原生支持多实例模式
-
template编译
vue2 编译 template 的源码中大量借助了正则表达式,而且是很复杂的正则表达式,所以在编译时效率其实是不高的,因为用正则覆盖复杂场景会导致正则表达式非常复杂,正则匹配的过程就需要不停的回溯,导致大量性能浪费
vue3中使用了类似 babel 编译的状态机模式,只需要遍历一次就可以完成编译,效率非常高,大家有兴趣可以自己下去了解一下