观察者模式(Observer):又被称为发布-订阅者模式。
DOM事件
DOM事件绑定就是最常见的发布-订阅模式
document.body.addEventListener('click', function(){
console.log('body1')
})
document.body.addEventListener('click', function(){
console.log('body2')
})
document.body.click(); //模拟用户点击
我们订阅了body的点击事件,当body被点击时,就会向订阅者发布这个消息
观察者模式的通用实现
在设计观察者对象的时候我们需要注意以下几个点:
- 有一个消息容器
- 三个方法:订阅消息方法、发送订阅消息的方法、取消订阅消息的的方法
const Observer = (function() {
// 存储消息
const messages = {};
return {
// 注册信息
regist(type, fn) {
let message = messages[type];
if (!message) {
messages[type] = [fn];
} else {
messages[type].push(fn);
}
},
// 发布信息
fire(type, args) {
let message = messages[type];
if (!message) {
return;
}
for (let i = 0; i < message.length; i++) {
message[i].call(this, {
type: type,
args: args,
});
}
},
// 删除信息
remove(type, fn) {
let message = messages[type];
if (message) {
let ind = message.indexOf(fn);
if (ind > -1) {
message.splice(ind, 1);
}
}
},
};
})();
/*测试*/
Observer.regist('test',function(e){
console.log(e.type); //注册的类型
console.log(e.arg); //发布的参数
})
Observer.fire('test',{msg:'参数'})
上面我们已经实现了观察者对象的基本功能,下面我们思考下面2个问题。
- 必须先订阅再发布吗?
- 全局事件的命名冲突
Vue中的观察者模式
双向数据 。。。待整理
小结
观察者模式的优点非常明显,一为时间上的解耦,二为对象之间的解耦。它的应用非常广泛,既可以用在异步编程中,也可以帮助我们完成更松耦合的代码编写。
创建订阅者本身要消耗一定的时间和内存,而且当你订阅一个消息后,也许此消息最后都未发生,但这个订阅者会始终存在于内存中。