手写一个发布-订阅模式
sisterAn opened this issue · comments
瓶子君 commented
class EventEmitter {
constructor() {
// 初始值为空对象
this.listeners = Object.create(null)
}
// 注册事件
on = (event, listener) => {
// this.bindEvent(event, listener, false)
if (!event || !listener) {
return
}
if (this.listeners[event]) {
//如果有就放一个新的
this.listeners[event].push(listener)
} else {
//如果没有就创建一个数组
this.listeners[event] = [listener]
}
}
// 只订阅一次
once = (event, listener) => {
// this.bindEvent(event, listener, true)
function one() {
// 在one函数运行原来的函数,只有将one清空
listener.apply(this, arguments)
// 先绑定 执行后再删除
this.off(event)
}
this.on(event, one)
//此时emit触发会执行此函数,会给这个函数传递rest参数
}
// 发布事件
emit = (event, ...args) => {
if (!this.hasBind(event)) {
console.warn(`this event: ${event} don't has bind listener.`)
return
}
this.listeners[event].forEach(listener => listener.call(this, ...args))
}
// 取消订阅
off = (event, listener) => {
if (!this.hasBind(event)) {
console.warn(`this event: ${event} don't exist.`)
return
}
// remove all listener
if (!listener) {
delete this.listeners[event]
return
}
// remove specific listener
this.listeners[event] = this.listeners[event].filter(item => item !== listener)
}
hasBind = event => {
return this.listeners[event]
&& this.listeners[event].length
}
}
// 测试
const baseEvent = new EventEmitter()
function cb(value){
console.log("hello "+value)
}
baseEvent.once("click",cb)
// baseEvent.off("click")
baseEvent.emit("click",'2020')
// hello 2020
console.log(baseEvent.listeners)
chenzhen commented
因该要加一个逻辑,不然该事件清除了,又调用解绑事件
if (this.listeners[event]) {
this.off(event)
}
omitchen commented
this.off(event)
执行一次把前面所有订阅的事件都卸载了,不太合适吧
xllpiupiu commented
/**
* https://blog.csdn.net/weixin_43792004/article/details/113442506
*/
//中间人 主题
class Dep {
constructor(callback) {
this.subs = []
this.callback = callback
}
addSub(sub) {
this.subs.push(sub)
return this
}
notify() {
this.subs.forEach(item=>item.update(this.callback))
}
}
//订阅者
class Sub {
constructor(val) {
this.val = val
}
update(callback) {
this.val = callback(this.val);
console.log('this.val: ', this.val);
}
}
//发布者
class Pub {
constructor() {
this.deps = []
}
addDep(dep) {
this.deps.push(dep)
}
removeDep(dep) {
let index = this.deps.indexOf(dep)
if(index!==-1) {
this.deps.splice(index,1)
return true
}
return false
}
publish(dep) {
this.deps.forEach(item=>item===dep&&item.notify())
}
}
let dep1 = new Dep(item=>item*item)
let sub1 = new Sub(3)
dep1.addSub(sub1)
let pub1 = new Pub()
pub1.addDep(dep1)
pub1.publish(dep1)