# 实现简易观察者模式和watch
实现 ob 和 watch 方法,希望当方法传入 watch 函数时会执行一次,之后每次修改 data 上的属性时,会触发对应的 console
const data = ob({ count: 0, foo: 'test' });
watch(() => {
console.log('watch-count', data.count);
});
watch(() => {
console.log('watch-foo', data.foo);
});
data.count += 1;
console.log('showcount', data.count);
delete data.count;
data.foo = 'test2';
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
实现: 主要是借助 Proxy/Reflect 进行检测代理, 一旦检测对象发生改变, 就触发watch的钩子函数
点击查看代码
const handlers = new Map()
function ob(data) {
return new Proxy(data, {
get(target, key, receiver) {
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver)
if (handlers.has(key)) {
handlers.get(key).forEach(handler => handler(value))
}
return result
},
deleteProperty(target, key) {
const result = Reflect.deleteProperty(target, key)
if (handlers.has(key)) {
handlers.get(key).forEach(handler => handler(undefined))
}
return result
}
})
}
function watch(handler) {
const observedKeys = new Set()
const observe = (key, handler) => {
if (!handlers.has(key)) {
handlers.set(key, new Set())
}
handlers.get(key).add(handler)
}
const unobserve = (key, handler) => {
if (handlers.has(key)) {
handlers.get(key).delete(handler)
}
}
const observeAll = () => {
Object.keys(data).forEach(key => {
observe(key, handler)
observedKeys.add(key)
})
}
const unobserveAll = () => {
observedKeys.forEach(key => {
unobserve(key, handler)
})
observedKeys.clear()
}
observeAll()
return {
observe,
unobserve,
observeAll,
unobserveAll,
}
}
const data = ob({ count: 0, foo: 'test' })
watch(() => {
console.log('watch-count', data.count);
});
watch(() => {
console.log('watch-foo', data.foo);
});
data.count += 1;
console.log('showcount', data.count);
delete data.count;
data.foo = 'test2';
// watch-count 1
// watch-foo test
// showcount 1
// watch-count undefined
// watch-foo test
// watch-count undefined
// watch-foo test2
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86