# Object的变化侦测
经过上一小节,相信大家对于Proxy
有一定的了解,本节将介绍Proxy
如何实现Object
的变化侦测。
# 监听get和set
我们使用Proxy
定义一个简单的方法
const obj = { a: 1 } const handlers = { get(target, key) { console.log(`getting ${key}`) return target[key] }, set(target, key, value) { console.log(`setting ${key} to ${value}`) return Reflect.set(target, key, value); } } const state = new Proxy(obj, handlers); state.a; // getting a state.a = 2; // setting a to 2
成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
执行上述代码,你会发现Proxy
会打印出getting
和setting
,说明Proxy
已经实现了最简单的对Object
的get
和set
的变化侦测。
有些同学可能会有疑问,为什么set
方法需要返回Reflect.set(target, key, value);
,而不是直接返回target[key] = value
?
因为Proxy
的set
方法需要返回一个布尔值,代表set
方法是否成功执行,如果直接返回target[key] = value
,那么Proxy
就无法知道set
方法是否成功执行了。
当然我们有很多方法去判断是否成功执行,但本着Proxy
和Reflect
对应的原则,这里我们使用ES6提供的对应的方法Reflect.set(target, key, value)
。
同样的,我们也可以把get
中的实现改为Reflect.get(target, key)
。
# 依赖收集和派发更新
我们之前说过,变化侦测,是指监测数据的变化情况,并在发生变化时更新视图。 要实现这个流程,我们除了监听数据之外,还需要收集对应的依赖和当依赖发生变更时,派发更新。
由此,我们可以将上述代码,改成如下
const obj = { a: 1 } // 依赖收集 function track(target, key) { console.log('依赖收集', key); } // 派发更新 function trigger(target, key) { console.log('触发更新', key); } const handlers = { get(target, key) { console.log(`getting ${key}`) // 依赖收集 track(target, key); return Reflect.get(target, key); }, set(target, key, value) { console.log(`setting ${key} to ${value}`) // 派发更新 trigger(target, key); return Reflect.set(target, key, value); } } const state = new Proxy(obj, handlers); state.a; state.a = 2;
成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
执行上述代码,可以得到如下打印内容
// 依赖收集 // getting a // setting a to 2 // 触发更新 // getting a
成功
1
2
3
4
5
2
3
4
5
那到目前为止,我们已经利用Proxy
实现了一个简单的响应式系统,能够监听数据的变化,收集依赖和派发对应的更新。我们接下来继续完善这个响应式系统的细节。