问:观察者模式和发布订阅模式的有什么区别?
答:https://juejin.im/post/5a14e9...
Google一下,相信都会有满屏的结果告诉你什么是发布订阅模式,但还是希望自己通过一些例子融入去实现.
概念理解:
① - 创建一个对象subscribers
存储所有订阅者与其fn.
② - 调用添加订阅者函数
时入参有(key,fn),将其存储到subscribers
.
subscribers[key].push(fn);
③ - 调用发布订阅信息函数
时再根据入参key,找到subscribers
中对应的订阅者并调用该数组下的所有fn.
④ - 取消订阅很简单,根据key在subscribers
找到对应的订阅者删除即可.
一、Just Do It
实现功能:
- 输入订阅者名称点击添加订阅者,已订阅用户列表添加一名订阅者,并附带取消订阅按钮
- 输入发布内容,点击发布给所有订阅者,用户列表所有订阅者接收显示一条新内容
- 输入发布内容,点击发布给指定订阅者,指定的订阅者接收显示一条新内容
- 点击取消订阅,删除对应订阅者信息
二、实现发布订阅Class
① - 添加订阅调用subscribe
,以key
为键名存储订阅者,fn为值存储回调函数.
② - 发布调用publish
根据key
找到对应的订阅者并调用其回调函数.
③ - key
等于all则发布给所有订阅者
④ - 取消订阅调用cancelSubscribe
,根据key
删除对应订阅者
<font color="orange">--- Code Example ---</font>
class SubscribePublish {
subs = {}; //存储订阅者
// 添加订阅
subscribe(key, fn) {
if (!this.subs[key]) this.subs[key] = [];
this.subs[key].push(fn)
console.log(key,'-----添加订阅-----');
}
// 发布订阅消息
publish(key,params) {
// 1.发布给所有订阅者
if(key === 'all'){
let allKey = Object.keys(this.subs);
allKey.forEach(key=>{
this.runCallback(this.subs[key],params);
})
return;
}
// 2.发布给指定订阅者
this.runCallback(this.subs[key],params);
console.log(key,'-----发布订阅消息-----');
}
// 执行订阅函数
runCallback(subs,params){
if (!Array.isArray(subs) || subs.length <= 0) return false;
let len = subs.length;
while (len--) {
subs[len].call(this, params);
}
}
// 取消订阅
cancelSubscribe(key){
if(this.subs[key]){
delete this.subs[key];
}
console.log(this.subs,'-----取消订阅-----');
}
}
三、功能实现阐述
// 实例化发布订阅Class
const subEvent = new SubscribePublish();
3.1 点击添加订阅
① - 获取input输入的订阅者名称,创建一个li+button标签 Dom元素并添加class以订阅者名称作为类名. (button=取消订阅按钮 & li=已订阅用户列表item)
② - 调用subEvent.subscribe(key,fn)
添加订阅者,入参key=input输入的订阅者名称 & fn=发布时调用的回调函数.
③ - 通过fn回调获取到公众号发布的内容,创建一个p
标签dom元素显示发布内容.
3.2 点击给(所有|指定)订阅者发布
① - 发布订阅只需要获取公众号发布的内容,点击时区分指定|所有调用subEvent.publish(key,content)
,publish会根据key值触发对应订阅者的回调函数.
② - 入参说明:
- key=all 发布订阅信息给所有订阅者
- key=name 发布给name订阅者
- content 要发布的内容
3.3 点击取消订阅
① - 3.1的时候,在添加订阅者时已经创建了一个button按钮,那么在创建的时候就已经添加了click事件监听.
② - 当点击取消订阅的时候,调用subEvent.cancelSubscribe(key)
删除对应订阅者并根据订阅者名称查找对应class类名的li标签将其Dom节点删除.
☺-End-☺
完整代码URL:
https://github.com/SmallFish-...
本文完 - 感谢阅读.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。