思路:
写一个on ,用于订阅监听事件,on(‘事件名’,fn) 把所有订阅了该事件名的fn放到一起,当发布该事件时,遍历执行这些fn,实现事件发布
写一个emit,用于发布事件,当emit触发时,所有订阅了此事件的订阅者将会触发事件(触发需要调用的函数)
写一个off,用于取消订阅事件
实现效果: 订阅者可以通过 on 函数订阅自定义事件,并上传一个发布时所触发的函数
发布者可以对 任意自定义事件 进行发布,
意思就是订阅了此事件的订阅者,可以执行上传的函数了,执行函数的顺序是,先订阅的先执行
并且发布者还能传参数给 订阅者的函数使用
// 这个xxx.js 是订阅发布的逻辑,导出此逻辑给其它模块引用
export const eventHub = {
// map 是消息队列,存储所有的订阅者,发布时,先订阅的先执行
map: {
// click: [f1 , f2 , ...]
// click1:[f1 , f2 , ...]
},
on: (name, fn) => { // name 是监听的事件名, fn 是监听的事件被发布后触发的函数,on是指订阅
//如果没有此事件就新建一个空数组以存储新事件
eventHub.map[name] = eventHub.map[name] || []
eventHub.map[name].push(fn)
},
emit: (name, data) => { // name 是需要发布的事件名,
//data 会传给所有订阅了此事件的订阅者,订阅了此事件的订阅者会接收data并传给 on 的 fn 函数
const q = eventHub.map[name]
if (!q) {console.error('不存在此事件'); return}
q.map(f => f.call(null, data))
return undefined
},
off: (name, fn) => { // 取消订阅
const q = eventHub.map[name]
if (!q) { return }
const index = q.indexOf(fn)
if (index < 0) { console.error('取消订阅失败'); return }
q.splice(index, 1)
console.log('取消订阅成功')
}
}
import {eventHub} from './xxx'
// main.js 订阅了同一个监听事件,但是触发的函数不同
eventHub.on('click', (data)=>{console.log('main.js的click事件被触发:' + data + '这句话代表不同的函数')})
eventHub.on('click', (data)=>{console.log('main.js的click事件被触发:' + data)})
// 如果订阅的事件不被发布,就不会被执行所传的函数
eventHub.on('upPage', (data)=>{console.log('main.js的upPage事件被触发:' + data)})
import {eventHub} from './xxx'
const fn1 = (data)=>{
console.log("test.js函数被触发" + data)
}
// test.js 订阅了一个名为click的事件
eventHub.on('click', fn1)
eventHub.off('click', fn1)
setTimeout(() => {
// 在一秒后发布此事件,所有订阅了click事件的订阅者
//将会接收到来自emit传的data('kasan')作为形参并传给订阅时所传的函数(fn1)
eventHub.emit('click', 'kasan')
}, 1000);
console.log(eventHub)
实际运行代码图没有下面的 upPage 因为被取消了