上一篇中提到了initData中会调用observe方法,然后会利用Object.defineProperty对data进行劫持,这里来简单实现以下响应式数据原理;
具体步骤如下:
- Observer对Obj的每一个属性调用defineReactive方法,defineReactive会使用Object.defineProperty来监听数据的get、set;
- Dep用来记录有哪些订阅者(Watcher)订阅了这个数据,并提供add方法添加订阅者(Watcher)、notify方法通知所有订阅者(Watcher)更新视图;
- 在defineReactive中会 new 一个 Dep(),Dep的subs中储存所有引用了该 data 的订阅者(Watcher);
- 如何向Dep的subs添加订阅者(Watcher)呢?Vue在定义数据劫持的getter时,如果存在静态属性Dep.target,则会调用当前Dep的addSub来添加一个订阅者(Watcher)到List;
- 什么时候创建(Watcher)呢? Vue在分析html模版时,一旦发现依赖了某个data,就会new 一个 Watcher();
- 若数据发生变化会调用Dep的notify()方法,遍历所有的订阅者(Watcher)并执行它们的update方法;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21// 定义数据,这里仅考虑Object形式
var data = { name: 'wdk', age: 25 }
function observe(obj) {
if (!obj || typeof obj !== 'object') return
var ob = new Observer(obj)
return ob
}
// 观察者
function Observer(obj) {
this.value = obj
this.walk(obj)
}
Observer.prototype.walk = function(obj) {
const keys = Object.keys(obj)
// 遍历数据&调用defineReactive
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i])
}
}
1 | function Dep() { |
1 | function update(value) { |