浅讨论下 vue2 和 vue3 的区别
vue2 是如何实现响应式的?
- 实现数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器
Observer
,用来监听所有属性。如果属性发生变化了,就需要告诉订阅者 Watcher
(Watcher 是一个封装了渲染视图逻辑的类,用于派发更新的),结合Vnode
经过patch()
中的diff算法
看是否需要更新(dep.notify() 通知 收集的 Watcher 重新渲染)。因为订阅者 Watcher
是有很多个,所以每一个属性都有自己的一个消息订阅器Dep
来专门收集这些订阅者(即以依赖的watcher
),然后在监听器 Observer
和订阅者Watcher
之间进行统一管理 - Dep 相当于把 Observe 监听到的信号做一个收集(collect dependencies),然后通过 dep.notify()再通知到对应 Watcher ,从而进行视图更新。
在数据劫持方面从 vue2 的 Object.defineProperty()升级为 Proxy,这样做有什么好处?
- 解决了在 vue2 中 set 方法监听不到数组的改变,无需重写 array 原型上的方法,因为数组也是对象,能够被监听到
- 给对象新增加一个属性时,不需要再手动去监听这个新增属性(使用 vm.$set 才能保证新增的属性也是响应式的)
- vue2 实现了一个
definedReactive
,内部是用Object.defineProperty
对每一个属性进行监听,需要遍历来对所有属性监听,只能监控到最外层的对象,深度监听一个对象时需要递归,Proxy 代理的是整个对象,而不是对象的某个特定属性,不需要我们通过遍历来逐个进行数据绑定 - 在使用 Object.defineProperty()给对象添加一个属性之后,我们对对象属性的读写操作仍然在对象本身。在 Proxy 中,如果想要读写操作生效,我们就要对 Proxy 的实例对象 proxyObj 进行操作。
defineProperty
实际上是对象的基本操作,而这些对象内部的基本操作,通过Proxy
暴露给开发者,这些13种拦截操作提供给开发者更多的操作空间(可以定义陷阱函数)proxyMdn (opens new window)
Vue3.0 优点
- 将 Vue 内部的绝大部分 api 对外暴露,使 Vue 具备开发大型项目的能力,例如 compile 编译 api 等
- webpack 的 treeshaking(tree shaking 是 DCE 的一种方式,它可以在打包时忽略没有用到的代码。)支持度友好
- 使用 Proxy 进行响应式变量定义,性能提高,对 typescript 支持更加友好
- 受 ReactHook 启发,可在 Vue2.0 中单独使用 composition-api 插件,或者直接用它开发插件
- Vue 3 的 Template 支持多个根标签,Vue 2 不支持
- Vue 3 的 v-if 优先于 v-for 生效,Vue2反之