https://juejin.im/post/5b125ad3e51d450688133f22
正好学习时看到这篇文章,不知是不是小伙伴写的,值得学习借鉴,就挪过来了
自定义事件 模子
js
let corp = {} // 自定义一个公司对象
corp.list = [] // 这里放一个列表用来缓存回调函数
// 订阅事件
corp.on = function(fn) {
this.list.push(fn)
}
// 发布事件
corp.emit = function() {
// 当发布时再把列表里存的函数依次执行
this.list.forEach(cb => {
cb.apply(this, arguments)
})
}
// 测试用例
corp.on((position, salary) => {
console.log(`职位:${position}, 薪水:${salary}`)
})
corp.on((skill, hobby) => {
console.log(`技能: ${skill}, 爱好: ${hobby}`)
})
corp.emit('前端', '10k')
corp.emit('端茶倒水', '把妹')上面这样写后, corp.emit 一次性把之前的信息都打印出来了,我们做点处理
js
let corp = {}
corp.list = {}
corp.on = function(key, fn) {
// 如果对象中没有对应key值,也就说明没有订阅过
// 那就给key创建个缓存列表
if (!this.list[key]) this.list[key] = []
// 把函数添加到对应key的缓存列表中
this.list[key].push(fn)
}
corp.emit = function() {
// 第一个参数是对应的key值
// 直接用数组的shift方法取出
let key = [].shift.call(arguments)
let fns = this.list[key]
// 如果缓存列表里没有函数就返回false
if (!fns || fns.length === 0) return false
// 遍历key值对应的缓存列表,依次执行函数的方法
fns.forEach(fn => fn.apply(this, arguments))
}
// 测试用例
corp.on('join', (position, salary) => {
console.log('你的职位是:' + position);
console.log('期望薪水:' + salary);
});
corp.on('other', (skill, hobby) => {
console.log('你的技能有: ' + skill);
console.log('爱好: ' + hobby);
});
corp.emit('join', '前端', 10000);
corp.emit('join', '后端', 10000);
corp.emit('other', '端茶和倒水', '足球');实现一个通用的发布订阅模式
思路:
- 创建一个对象(缓存列表)
- on方法用来把回调函数fn都加到缓存列表中
- emit方法取到arguments里第一项当做key,根据key值去执行对应缓存列表中的函数
- remove方法可以根据key值取消订阅
js
class CustomEvent {
constructor() {
this.list = {}
}
on(key, fn) {
if (!this.list[key]) this.list[key] = []
this.list[key].push(fn)
}
emit() {
let key = [].shift.call(arguments)
let fns = this.list[key]
if (!fns || fns.length === 0) return false
fns.forEach(fn => fn.apply(this, arguments))
}
off(key, fn) {
// 取消订阅
let fns = this.list[key]
// 如果缓存列表中没有函数,返回false
if (!fns) return false
// 如果没有传对应函数,就会将key值对应缓存列表中的函数都清空掉
if (!fn) {
fns && (fns.length = 0)
} else {
// 遍历缓存列表,看看传入的fn与哪个函数相同
// 如果相同就直接从缓存列表中删除即可
fns.forEach((cb, i) => {
if (cb === fn) fns.splice(i, 1)
})
}
}
}总结
优点:
- 对象间的解耦
- 异步编程中,可以更松耦合地代码编写
缺点:
- 创建订阅者本身要消耗一定的时间和内存
- 多个发布者和订阅者嵌套一起时,程序难以跟踪维护
