JavaScript- 消息订阅发布模式探究
1. 消息订阅发布模式在实际项目开发中的应用
- React项目中, 非父子(兄弟)组件间的通信
- Vue的响应式原理: 采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,
在数据变动时发布消息给订阅者,触发相应的监听回调
2. 什么是消息订阅-发布模式
- 打个比方,比如小红和小明想阅读一份报纸, 但是却懒得每次到书报摊去买报纸; 因此他们选择了订阅该期刊, 当每个月有新期刊发布时, 邮递员会按时把当日的报纸投送到他们的信箱中去; 在这个场景中, 邮递员定时投递报刊就是一种消息订阅-发布模式
- 用专业术语来讲; 消息订阅-发布模式就是多个订阅者(一般是注册的函数)同时监听同一个数据对象,当这个数据对象发生变化的时候会执行一个发布事件,通过这个发布事件会通知到所有的订阅者,使它们能够自己改变对数据对象依赖的部分状态。
3. 消息发布-订阅模式的优缺点
- 优点:耦合性低,便于代码的维护; 能快速实现兄弟组件间的数据通信
- 缺点: 创建订阅者本身要消耗一定的时间和内存,可能订阅的消息未发生,但这个订阅者会始终存在于内存中
4. 代码示例:
思路:
1, 创建一个管理对象, 数组list由于存储订阅者及其传递的函数 2, 创建方法: - 订阅消息 - 发布消息 - 删除订阅
declare interface IPubsub {
list: Array<unknown>,
addListener: (key: string, fn: Function) => void,
publish: () => void
removeListener: (key: string, fn: Function) => void | false
}
const shopObj: IPubsub = {
list: [],
addListener: function (key, fn) {
if (!this.list[key]) {
this.list[key] = [];
}
this.list[key].push(fn);
},
publish: function () {
let key = Array.prototype.shift.call(arguments);
const funcs = this.list[key];
if (!funcs || funcs.length === 0) {
console.log("no relevant subscriber")
return
}
for (let i = 0; i < funcs.length; i++) {
funcs[i].apply(this, arguments)
}
},
removeListener(key: string, fn: Function | null): void | false {
const fns = this.list[key]
if (fn === null) {
fns.length = 0;
return
}
if (!fns) {
fns && (fns.length = 0);
return false
} else {
for (let i = fns.length - 1; i >= 0; i--) {
let _fn = fns[i]
if (_fn === fn) {
fns.splice(i, 1)
}
}
}
}
}
5. 测试消息的订阅- 发布
shopObj.addListener("xm", size => {
console.log(`xm size is ${size}`)
})
shopObj.addListener("张三", size => {
console.log(`zhangsan size is ${size}`)
})
shopObj.publish("张三", 120)
shopObj.removeListener("张三", null)
shopObj.publish("张三", 120)
|