hg-sid
Version:
a front-end simple framework with mvc
89 lines (81 loc) • 2.31 kB
text/typescript
import DDClass from '.'
export default function evDecorator(DD: typeof DDClass) {
let proto = DD.prototype
proto._events = {}
proto.$on = function (
eventName: string | Array<string>,
fn: Function[] | Function
): any {
let object = this
if (Array.isArray(eventName)) {
// 处理事件名是数组的情况
eventName.forEach(name => this.$on(name, fn))
} else {
// 将 fn 统一转化为数组来处理
if (!Array.isArray(fn)) fn = [fn]
// 若 _events 对象下无对应事件名,则新建一个数组,然后将处理函数推入数组
;(object._events[eventName] || (object._events[eventName] = [])).push(...fn)
}
return object
}
proto.$once = function (eventName: string | Array<string>, fn: Function): any {
let object = this
function on() {
// 先取消,然后触发,确保仅一次
object.$off(eventName, on)
// 闭包 fn 被保存在外部
fn.apply(object, arguments)
}
object.$on(eventName, on)
return object
}
proto.$off = function (eventName?: string | Array<string>, fn?: Function): any {
let object = this
// 清空所有事件
if (!arguments.length) {
object._events = {}
return object
}
// 清空多个事件
if (Array.isArray(eventName)) {
eventName.forEach(name => this.$off(name, fn))
return object
}
// 若没有事件对应的函数列表则不用处理
const cbs = object._events[eventName]
if (!cbs) {
return object
}
// 清空特定事件
if (!fn) {
object._events[eventName] = null
return object
}
// 取消特定事件的特定处理函数
if (fn) {
let cb
let i = cbs.length
// 处理一次取消多个的情况
if (Array.isArray(fn)) {
fn.forEach(fnc => this.$off(eventName, fnc))
return
}
while (i--) {
cb = cbs[i]
if (cb === fn || cb.fn === fn) {
cbs.splice(i, 1)
break
}
}
}
return object
}
proto.$emit = function (eventName: string, ...args: any[]): any {
let object = this
let cbs: Function[] = object._events[eventName]
if (cbs) {
cbs.forEach(func => func.apply(object, args))
}
return object
}
}