Twlig / issuesBlog

MIT License
3 stars 0 forks source link

变化侦测原理 #39

Open Twlig opened 2 years ago

Twlig commented 2 years ago

变化侦测

Object变化侦测

Data通过Observer转换成getter/setter的形式来追踪变化(主要是Object.defineProperty)。

每个Observer中都有Dep实例,用于记录依赖(依赖就是Watcher)。

当外界通过Watcher读取数据时,会触发getter从而将Watcher添加到Observer的Dep实例中

当数据发生变化时,会触发setter,从而向Dep中的依赖(Watcher)发送通知

Watcher接受到通知后,会向外界发送通知,外界可能会触发试图更新或者执行某个回调函数

image

总结:在getter中收集依赖,在setter中触发依赖

Array变化侦测

Object采用defineProperty通过getter/setter方法实现变化侦测。而Array没有,因此需要采用拦截器覆盖Array.prototype,在拦截器中定义push等方法新增变化侦测的代码。这样每次使用如push等数组操作时,执行的都是拦截器中定义的push方法,就可以实现变化侦测。

  1. 对于支持__proto__属性的浏览器采用拦截器方法覆盖原型

    arr.__proto__ = arrayMethods
  2. 对于不支持的浏览器,采用拦截器方法直接添加在数组实例上

    arr.push = arrayMethods['push']

总结:在getter中收集依赖,在拦截器中触发依赖

Twlig commented 2 years ago

变化侦测存在的问题

  1. object对象添加属性和删除属性无法被侦测到。因为defineProperty只能追踪一个数据是否被修改无法追踪新增属性和删除属性。通过vm.$set和vm.$delete可以解决。
  2. array数组通过原生操作修改数据无法被侦测,如arr[0] = 1; arr.length = 0;