vue2 与 vue3 区别
- api不同
vue2 选项式 Opation API
vue3 组合式 Component API
- 响应式不同
vue2:
基于Object.defineProperty(属性级)进行数据劫持,结合发布订阅模式实现;
数据劫持:
Object.defineProperty会遍历data中所有的property
为每一个属性添加了getter和setter
getter:读取属性时触发,依赖收集(记录那些地方用了什么属性,使用watch...)
setter:修改属性时触发,通知更新(告诉依赖哪些地方需要重新计算,或渲染模版...)
发布-订阅模式:
依赖管理器:Dep: 每一个响应式属性维护一个Dep
订阅者:Watcher:关联到视图或者逻辑,当Dep告诉Watch更新,执行具体更新
流程:
1.初始:观察者(Observer)会遍历所有的data,用Object.defineProperty劫持所有属性,并给每个属性添加依赖管理器(Dep)
2.渲染: render函数会访问响应式属性,触发getter,Dep收集当前所有依赖,渲染Watcher
3.修改:触发setter方法,Dep通知所有订阅的Watch,执行更新
缺陷:
1.数据劫持局限:无法监听数组下标,方法,长度等等实现响应式,对数组处理有难度增加;
2.无法监听新增/删除属性:Object.defineProperty只能对初始化的数据进行数据劫持,如果动态增加或者删除属性,无法触发响应式,需要使用(Vue.set/Vue.delete)
vue3:
基于Proxy(对象级)去代理对象,配合Reflect去实现强大的响应式,结合依赖追踪和更新机制,但底层还是劫持方式实现;
数据劫持:
Proxy包裹目标对象,拦截对象的所有操作
get拦截: 读取属性时触发,依赖收集
set拦截: 修改属性时触发,通知更新
其他拦截(deletPropery,...):支持监听属性的删除...;
依赖管理:
通过副作用(effect)收集依赖,track(追踪依赖)和tigger(触发更新)实现响应式更新;
流程:
1.通过ref(reactive)创建响应式数据,返回Proxy代理后的对象;
2.访问属性:Proxy中的get拦截器触发,tarck获取effect中当前的依赖;
3.修改属性:Proxy中的set拦截器触发,tigger通知所有关联的effect执行更新;
优势:
1.支持动态属性变化:Proxy直接代理整个对象,新增删除都可以被监听;
2.数组劫持更自然:不需要重新数组,Proxy代理后可以直接进行数据操作,响应式更加彻底;
3.性能优化:Proxy实现响应式,在初始化和更新时候都可以进行劫持数据,依赖被统一收集,减少代码的冗余;