/**
* 实现一个简单的观察者模式
*/
const shop = {
apple: 5, // 苹果5元
potato: 2, // 马铃薯 2元
tomato: 3, // 西红柿 3元
orange: 7,
}
/**
* 现在我们有一个便利店的实例对象,目标是需要增加对商品价格的监听,当商品价格发生变化时,触发对应的事件。
* 1、小明关注苹果价格变化
* 2、小刚关注橙子价格变化
* 3、当价格变化时,自动触发对应的事件
*/
class Pubsub {
constructor() {
}
list = {};
// 监听方法,添加监听者,监听对象,和监听事件的方法
listen = (key, listener, fn) => {
const { list = {} } = this;
if (!list[key]) {
list[key] = [];
}
list[key].push({ listener, fn });
return () => this.remove(key, listener, fn);
}
// 发布消息的方法
publish = (key, price) => {
const { list = {} } = this;
if (list[key]) {
list[key].forEach((item) => {
const { listener, fn } = item;
fn.call(null, listener, price);
})
}
}
// 移除监听的方法
remove = (key, listener, fn) => {
const { list = {} } = this;
if (!listener) { // 如果没有传入监听人,则移除对该属性的所有监听
delete list[key];
return;
}
if (!fn || typeof fn !== 'function') { // 如果没有传入fn,则移除此监听者的所有监听事件
list[key] = list[key].filter(x => x.listener !== listener);
return;
}
const index = list[key].findIndex(x => x.listener === listener && x.fn === fn);
list[key].splice(index, 1);
if (list[key].length === 0) { // 如果移除监听后,监听列表的长度变为0, 则移除这个监听
delete list[key];
}
}
}
const pubsub = new Pubsub();
const event1 = pubsub.listen('apple', '小明', (listener, price) => {
console.log(`${listener}关注的apple的最新价格是${price}`);
})
const enent2 = pubsub.listen('orange', '小明', (listener, price) => {
console.log(`${listener}关注的orange的最新价格是${price}`);
})
const enent3 = pubsub.listen('orange', '小刚', (listener, price) => {
console.log(`${listener}关注的orange的最新价格是${price}`);
})
const set = (target, key, value, receiver) => {
if (receiver[key] !== value) {
pubsub.publish(key, value);
}
return Reflect.set(target, key, value, receiver);
}
const observable = (obj) => new Proxy(obj, { set });
const newShop = observable(shop);
newShop.apple = 5;
newShop.apple = 6;
/** 小明关注了苹果的价格,苹果价格变更将会触发事件
** console.log将会输出: 小明关注的apple的最新价格是6元
**/
newShop.tomato = 10;
/** 无人关注西红柿价格,不会触发事件 **/
newShop.orange = 11;
/** 小明关注了橙子的价格,橙子价格变更将会触发事件
** console.log将会输出: 小明关注的orange的最新价格是11元
**/
/** 小刚关注了橙子的价格,橙子价格变更将会触发事件
** console.log将会输出: 小刚关注的orange的最新价格是11元
**/
// 移除小明对app事件的监听
event1();
newShop.apple = 7;
/** 苹果监听已经被移除,无人关注苹果价格,不会触发事件 **/
newShop.orange = 12;
/** 小明关注了橙子的价格,橙子价格变更将会触发事件
** console.log将会输出: 小明关注的orange的最新价格是12元
**/
/** 小刚关注了橙子的价格,橙子价格变更将会触发事件
** console.log将会输出: 小刚关注的orange的最新价格是12元
**/