前言:发布订阅模式,还具有解除订阅功能
模拟实现
function fn1(n1, n2) {console.log('first add', n1, n2)}
function fn2(n1, n2) {console.log('second add', n1, n2)}
function fn3(n1, n2) {console.log('third add', n1, n2)}
class MYVue {
constructor() {
this._events = Object.create(null) // 存放各种自定义事件的对象
}
$on(event, fn) {
if (Array.isArray(event)) {
event.forEach(v => {this.$on(v, fn)})
} else {
if (!this._events[event]) this._events[event] = []
this._events[event].push(fn)
}
}
$off(event, fn) {
if (!arguments.length) { // 移除所有事件
this._events = Object.create(null)
return
}
if (Array.isArray(event)) {
event.forEach(v => {this.$off(v, fn)})
return
}
const item = this._events[event]
if (!item) return
if (!fn) { // 移除某个事件所有订阅的函数
this._events[event] = null
return
}
const it = item.findIndex(v => v === fn)
if (it !== -1) item.splice(it,1)
}
$once(event, fn) {
function on() {
this.$off(event, on)
fn.apply(this, arguments)
}
on.fn = fn
this.$on(event, on)
}
$emit(event) {
let item = this._events[event]
if (!item) return
item.forEach(fn => {
fn.apply(this, [...arguments].slice(1))
})
}
}
const myvue = new MYVue()
myvue.$on('first',fn1)
myvue.$on('second',fn2)
myvue.$once('third',fn3)
myvue.$emit('first', 20, 30)
myvue.$emit('second', 60, 70)
myvue.$emit('third', 100, 200)