数据的双向绑定的原理
重构响应式系统,使用Proxy替换Object.defineProperty
Object.defineProperty的原理:通过使用 Object.defineProperty 来劫持对象属性的 geter 和 seter 操作,当数据发生改变发出通知。Vue2.x版本中的双向绑定不能检测到下标的变化。
porxy原理:通过ES6的新特性proxy来劫持数据,当数据改变时发出通知。proxy可以劫持整个对象,并返回一个新对象。
性能的提升
diff方法优化
Vue2 中的虚拟dom是进行全量的杜比
Vue3 新增了静态标记(PatchFlag),只比对带有 PF 的节点,并且通过 Flag 的信息得知
当前节点要比对的具体内容。
静态提升
Vue2中无论元素是否参与更新, 每次都会重新创建, 然后再渲染
Vue3中对于不参与更新的元素, 会做静态提升, 只会被创建一次, 在渲染时直接复用即可
cacheHandlers 事件侦听器缓存
Vue2默认情况下onClick会被视为动态绑定, 所以每次都会去追踪它的变化
Vue3但是因为是同一个函数,所以没有追踪变化, 直接缓存起来复用即可
ssr渲染
Vue2当有大量静态的内容时候,这些内容会被当做纯字符串推进一个buffer里面, 即使存在动态的绑定,会通过模板插值嵌入进去。这样会比通过虚拟dmo来渲染的快上很多很多。
Vue3当静态内容大到一定量级时候,会用_createStaticVNode方法在客户端去生成一个static node,这些静态node,会被直接innerHtml,就不需要创建对象,然后根据对象渲染。
按需编译,体积更小(Tree shaking)
Tree-shaking 使编译更友好,比如,如果你的项目没有用到watch,那编译时就会把tree shaking掉。
Compostion API: 组合API/注入API
Vue2的组件内,使用的是Option API风格(data/methods/mounted)来组织的代码,这样会让逻辑分散,举个例子就是我们完成一个计数器功能,要在data里声明变量,在methods定义响应函数,在mounted里初始化变量,如果在一个功能比较多、代码量比较大的组件里,你要维护这样一个功能,就需要在data/methods/mounted反复的切换到对应位置,然后进行代码的更改。
Vue3中,使用setup函数。如下所示跟count相关的逻辑,都放到counter.js文件里,跟todo相关的逻辑放到todos.js里。
自定义渲染API(Custom Renderer API)
Vue2.x最开始支持运行在浏览器中,渲染到浏览器的dom上,随着vue的流行,出现了weex和myvue。
Vue2.x项目架构对于这种渲染到不同平台不太友好,
Vue3.0推出了自定义渲染API解决了该问题。
vue官方实现的 createApp 会给我们的 template 映射生成 html 代码,但是要是你不想渲染生成到 html ,而是要渲染生成到 canvas 之类的不是html的代码的时候,那就需要用到 Custom Renderer API 来定义自己的 render 渲染生成函数了。
vite开发构建工具
Vue2是使用webpack作为开发构建工具的,npm run dev都要等一会,项目越大等的时间越长
Vue3是使用vite来做开发构建工具。vite支持浏览器支持import关键字,启动项目时浏览器直接请求路由对应的代码文件,代理服务器针对单个文件进行编译并返回。如果请求的文件里还import了其他文件,同理浏览器继续发请求,代理服务器返回。就这样实现了npm run dev时无需编译,实时请求实时编译。
支持TS语法
Vue2结合ts的具体实践中,要用 vue-class-component 强化 vue 组件,让 Script 支持 TypeScript 装饰器,用 vue-property-decorator 来增加更多结合 Vue 特性的装饰器,最终搞的ts的组件写法和js的组件写法差别挺大。
Vue3量身打造了defineComponent函数,使组件在ts下,更好的利用参数类型推断 。Composition API 代码风格中,比较有代表性的api就是 ref 和 reactive,也很好的支持了类型声明。