106 lines
2.4 KiB
TypeScript
106 lines
2.4 KiB
TypeScript
import { isArray } from '@vue/shared'
|
|
import { ComponentInternalInstance } from '../component'
|
|
import { callWithAsyncErrorHandling, ErrorCodes } from '../errorHandling'
|
|
import { assertCompatEnabled } from './compatConfig'
|
|
import { DeprecationTypes } from './deprecations'
|
|
|
|
interface EventRegistry {
|
|
[event: string]: Function[] | undefined
|
|
}
|
|
|
|
const eventRegistryMap = /*#__PURE__*/ new WeakMap<
|
|
ComponentInternalInstance,
|
|
EventRegistry
|
|
>()
|
|
|
|
export function getRegistry(
|
|
instance: ComponentInternalInstance
|
|
): EventRegistry {
|
|
let events = eventRegistryMap.get(instance)
|
|
if (!events) {
|
|
eventRegistryMap.set(instance, (events = Object.create(null)))
|
|
}
|
|
return events!
|
|
}
|
|
|
|
export function on(
|
|
instance: ComponentInternalInstance,
|
|
event: string | string[],
|
|
fn: Function
|
|
) {
|
|
if (isArray(event)) {
|
|
event.forEach(e => on(instance, e, fn))
|
|
} else {
|
|
if (event.startsWith('hook:')) {
|
|
assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS)
|
|
} else {
|
|
assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER)
|
|
}
|
|
const events = getRegistry(instance)
|
|
;(events[event] || (events[event] = [])).push(fn)
|
|
}
|
|
return instance.proxy
|
|
}
|
|
|
|
export function once(
|
|
instance: ComponentInternalInstance,
|
|
event: string,
|
|
fn: Function
|
|
) {
|
|
const wrapped = (...args: any[]) => {
|
|
off(instance, event, wrapped)
|
|
fn.call(instance.proxy, ...args)
|
|
}
|
|
wrapped.fn = fn
|
|
on(instance, event, wrapped)
|
|
return instance.proxy
|
|
}
|
|
|
|
export function off(
|
|
instance: ComponentInternalInstance,
|
|
event?: string,
|
|
fn?: Function
|
|
) {
|
|
assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER)
|
|
const vm = instance.proxy
|
|
// all
|
|
if (!arguments.length) {
|
|
eventRegistryMap.set(instance, Object.create(null))
|
|
return vm
|
|
}
|
|
// array of events
|
|
if (isArray(event)) {
|
|
event.forEach(e => off(instance, e, fn))
|
|
return vm
|
|
}
|
|
// specific event
|
|
const events = getRegistry(instance)
|
|
const cbs = events[event!]
|
|
if (!cbs) {
|
|
return vm
|
|
}
|
|
if (!fn) {
|
|
events[event!] = undefined
|
|
return vm
|
|
}
|
|
events[event!] = cbs.filter(cb => !(cb === fn || (cb as any).fn === fn))
|
|
return vm
|
|
}
|
|
|
|
export function emit(
|
|
instance: ComponentInternalInstance,
|
|
event: string,
|
|
...args: any[]
|
|
) {
|
|
const cbs = getRegistry(instance)[event]
|
|
if (cbs) {
|
|
callWithAsyncErrorHandling(
|
|
cbs,
|
|
instance,
|
|
ErrorCodes.COMPONENT_EVENT_HANDLER,
|
|
args
|
|
)
|
|
}
|
|
return instance.proxy
|
|
}
|