Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

变化侦测原理 #39

Open
Twlig opened this issue Mar 16, 2022 · 1 comment
Open

变化侦测原理 #39

Twlig opened this issue Mar 16, 2022 · 1 comment
Labels

Comments

@Twlig
Copy link
Owner

Twlig commented Mar 16, 2022

变化侦测

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 Twlig added the Vue label Mar 16, 2022
@Twlig
Copy link
Owner Author

Twlig commented Mar 16, 2022

变化侦测存在的问题

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant