Appearance
发布订阅模式
什么是发布订阅模式,例如 addEventListener,Vue evnetBus 都属于发布订阅模式
on订阅/监听
emit 发布/注册
once 只执行一次
off解除绑定
rollup 编译
具体代码
ts
interface EventFace {
on: (name: string, callback: Function) => void
emit: (name: string, ...args: Array<any>) => void
once: (name: string, fn: Function) => void
off: (name: string, fn: Function) => void
}
interface Obj {
[key: string]: Array<Function>
}
export class Dispatch implements EventFace {
obj: Obj
constructor() {
this.obj = {}
}
on(name: string, callback: Function) {
const callbackList = this.obj[name] || []
callbackList.push(callback)
this.obj[name] = callbackList
console.log(this.obj)
}
emit(name: string, ...args: Array<any>) {
let eventName = this.obj[name]
if (eventName) {
eventName.forEach(fn => {
fn.apply(this, args)
})
} else {
console.error(`输入的${name}名称错误`)
}
}
once(name: string, fn: Function) {
// 临时函数
let de = (...args: Array<any>) => {
fn.apply(this, args)
this.off(name, de)
}
this.on(name, de)
}
off(name: string, fn: Function) {
let eventName = this.obj[name]
if (eventName && fn) {
let index = eventName.findIndex(fns => fns === fn)
eventName.splice(index, 1)
} else {
console.error(`输入的${name}名称错误`)
}
}
}TIP
可以理解成 on 方法向中间存储对象的name属性的回调数组中,存一个新的回调函数,在外部调用的时候里面写接受参数的逻辑
emit 方法就是用来发送数据,通过 name 找到属于这个name属性的回调集合,集合中的回调函数使用apply方法,进行动态传参
apply
index.html
html
<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>ts-rollup</title>
</head>
<script type="module">
import {Dispatch} from '../lib/index.js'
const o = new Dispatch()
o.on('Gxx', (...args) => {
console.log(args, 112312)
})
// const fn = (...args) => {
// console.log(args,23423)
// }
// o.on('Gxx', fn)
// o.off('Gxx',fn)
o.once('Gxx', (...args) => {
console.log(args, 'once')
})
o.emit('Gxx', 1, false, {name: 'zx'})
o.emit('Gxx', 2, false, {name: 'zx'})
</script>
<body>
</body>
</html>