# 发布订阅模式定义
注意: 观察者模式 和 发布订阅模式 不是相同的概念哦注意: 观察者模式 和 发布订阅模式 不是相同的概念哦注意: 观察者模式 和 发布订阅模式 不是相同的概念哦
- 思路:
- 新建Dep类, 在属性劫持时(可以采用观察者), 往Dep中给每个属性绑定一个Watcher对象(订阅动作)
- 当属性触发set方法时, 调用Dep里所有的watcher执行(发布动作)
- Watcher里是更新DOM操作的
- 代码如下:
function myObjectDefinePropery(data, key, val) {
if (val && typeof val === 'object') {
observe(val);
return;
}
// 7. 实例化Dep类对象(每个key都有一个Dep, 负责桥接属性变化和Watcher的)
// 因为一个key可能触发多个要执行的函数, 函数用Watcher装载
let dep = new Dep();
Object.defineProperty(data, key, {
get: function() {
// 8. (Dep.target 指的是Watcher实例对象, 如果有, 则添加到Dep对象上)
if (Dep.target){
// 9. 添加Watcher到Dep对象中
dep.addSub(Dep.target);
}
return val;
},
set: function(newVal) {
// 判断set时值一样则退出
if (val === newVal){
return;
}
val = newVal;
// 10. 属性发生变化, 通知Dep, 调用所有Wathcer执行对应方法(发布订阅模式核心-要发布了)
dep.notify();
}
});
}
function observe(data) {
Object.keys(data).forEach(function(key) {
myObjectDefinePropery(data, key, data[key]);
});
}
// 1. 新建Dep类, 属性改变, 触发方法, 收集这些方法
function Dep () {
// 用于放置每个属性变化时应该执行的方法体
this.watcherArr = [];
}
Dep.prototype = {
// 2. 用于添加属性改变对应执行的方法
addSub: function(watcher){
this.watcherArr.push(watcher);
},
// 3. 用于通知所有watcher, 让watcher执行自己对应的方法体
notify: function(){
this.watcherArr.forEach(function(watcher){
// 4. 执行对应代码, 可以跳转到Watcher类的update方法查看
watcher.update();
})
}
};
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
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
← 父子组件双向绑定