# 发布订阅模式定义

注意: 观察者模式 和 发布订阅模式 不是相同的概念哦注意: 观察者模式 和 发布订阅模式 不是相同的概念哦注意: 观察者模式 和 发布订阅模式 不是相同的概念哦

  1. 思路:
  • 新建Dep类, 在属性劫持时(可以采用观察者), 往Dep中给每个属性绑定一个Watcher对象(订阅动作)
  • 当属性触发set方法时, 调用Dep里所有的watcher执行(发布动作)
  • Watcher里是更新DOM操作的
  1. 代码如下:
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
上次更新时间: 7/12/2020, 5:58:02 PM