一,数组和对象的深度监听
处理方法 数据测试1,Object.defineProperty缺点
1)深度监听,需要递归到底,一次性计算量大
2)无法监听新增属性/删除属性(Vue.set,Vue.delete)
3)无法原生监听数组,需要特殊处理
2,数组监听:就是重写了数组的原型,更准确的表达是拦截了数组的原型,然后用Object.defineProperty劫持数组方法
2,vue3.0,Object.defineProperty的替代方案是proxy(不能兼容ie11)、
二,响应式的核心原理
1,Observer
将data中的数据用Object.defineProperty进行数据劫持,每个目标对象的键值(即data中的数据)转换成getter/setter形式,用于进行依赖收集和通过依赖通知更新
2,Dep(依赖管理)
1)什么是依赖?
数据响应式后,如何通知视图更新?Dep就是帮我们收集【究竟要通知到哪里的】
2)如何收集依赖
我们如何知道data中的某个属性被使用了,答案就是Object.defineProperty,因为读取某个属性就会触发get方法
3)Dep就是收集与视图相关的数据,触发了get的数据,主要起到依赖收集和通知更新的作用。用于收集当前响应式对象的依赖关系,每个响应式对象包括子对象都拥有一个 Dep 实例(里面 subs 是 Watcher 实例数组),当数据有变更时,会通过 dep.notify()通知各个 watcher。
4)initState 时,对 computed 属性初始化时,触发 computed watcher 依赖收集
5)initState 时,对侦听属性初始化时,触发 user watcher 依赖收集
6)render()的过程,触发 render watcher 依赖收集
7)re-render 时,vm.render()再次执行,会移除所有 subs 中的 watcer 的订阅,重新赋值。
3,Watcher
1)Watcher就是类似中介的角色,比如message就有三个中介,当message变化,就通知这三个中介,他们就去执行各自需要做的变化。
2)Watcher必须要有的2个方法。一个就是通知变化,另一个就是被收集起来到Dep中去。
3)遍历所有的 subs(Watcher 实例),调用每一个 watcher 的 update 方法。
4,Watcher 和 Dep 的关系
watcher 中实例化了 dep 并向 dep.subs 中添加了订阅者,dep 通过 notify 遍历了 dep.subs 通知每个 watcher 更新。
三,总结
1,在数据被改的时候,触发set方法,通过对应的所有依赖(Watcher),去执行更新。比如watch和computed就执行开发者自定义的回调方法。
2,Observer中进行响应式的绑定,在数据被读的时候,触发get方法,执行Dep来收集依赖,也就是收集Watcher。
网友评论