问:观察者模式和发布订阅模式的有什么区别?
答: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,'-----取消订阅-----'); } }
三、功能实现阐述
// 实例化发布订阅Classconst 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-...
本文完 - 感谢阅读.