diff options
Diffstat (limited to 'node_modules/vue/src/core/instance/events.js')
| -rw-r--r-- | node_modules/vue/src/core/instance/events.js | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/node_modules/vue/src/core/instance/events.js b/node_modules/vue/src/core/instance/events.js new file mode 100644 index 00000000..58779996 --- /dev/null +++ b/node_modules/vue/src/core/instance/events.js @@ -0,0 +1,142 @@ +/* @flow */ + +import { + tip, + toArray, + hyphenate, + handleError, + formatComponentName +} from '../util/index' +import { updateListeners } from '../vdom/helpers/index' + +export function initEvents (vm: Component) { + vm._events = Object.create(null) + vm._hasHookEvent = false + // init parent attached events + const listeners = vm.$options._parentListeners + if (listeners) { + updateComponentListeners(vm, listeners) + } +} + +let target: any + +function add (event, fn, once) { + if (once) { + target.$once(event, fn) + } else { + target.$on(event, fn) + } +} + +function remove (event, fn) { + target.$off(event, fn) +} + +export function updateComponentListeners ( + vm: Component, + listeners: Object, + oldListeners: ?Object +) { + target = vm + updateListeners(listeners, oldListeners || {}, add, remove, vm) + target = undefined +} + +export function eventsMixin (Vue: Class<Component>) { + const hookRE = /^hook:/ + Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component { + const vm: Component = this + if (Array.isArray(event)) { + for (let i = 0, l = event.length; i < l; i++) { + this.$on(event[i], fn) + } + } else { + (vm._events[event] || (vm._events[event] = [])).push(fn) + // optimize hook:event cost by using a boolean flag marked at registration + // instead of a hash lookup + if (hookRE.test(event)) { + vm._hasHookEvent = true + } + } + return vm + } + + Vue.prototype.$once = function (event: string, fn: Function): Component { + const vm: Component = this + function on () { + vm.$off(event, on) + fn.apply(vm, arguments) + } + on.fn = fn + vm.$on(event, on) + return vm + } + + Vue.prototype.$off = function (event?: string | Array<string>, fn?: Function): Component { + const vm: Component = this + // all + if (!arguments.length) { + vm._events = Object.create(null) + return vm + } + // array of events + if (Array.isArray(event)) { + for (let i = 0, l = event.length; i < l; i++) { + this.$off(event[i], fn) + } + return vm + } + // specific event + const cbs = vm._events[event] + if (!cbs) { + return vm + } + if (!fn) { + vm._events[event] = null + return vm + } + if (fn) { + // specific handler + let cb + let i = cbs.length + while (i--) { + cb = cbs[i] + if (cb === fn || cb.fn === fn) { + cbs.splice(i, 1) + break + } + } + } + return vm + } + + Vue.prototype.$emit = function (event: string): Component { + const vm: Component = this + if (process.env.NODE_ENV !== 'production') { + const lowerCaseEvent = event.toLowerCase() + if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) { + tip( + `Event "${lowerCaseEvent}" is emitted in component ` + + `${formatComponentName(vm)} but the handler is registered for "${event}". ` + + `Note that HTML attributes are case-insensitive and you cannot use ` + + `v-on to listen to camelCase events when using in-DOM templates. ` + + `You should probably use "${hyphenate(event)}" instead of "${event}".` + ) + } + } + let cbs = vm._events[event] + if (cbs) { + cbs = cbs.length > 1 ? toArray(cbs) : cbs + const args = toArray(arguments, 1) + for (let i = 0, l = cbs.length; i < l; i++) { + try { + cbs[i].apply(vm, args) + } catch (e) { + handleError(e, vm, `event handler for "${event}"`) + } + } + } + return vm + } +} |
