aboutsummaryrefslogtreecommitdiff
path: root/node_modules/vue/src/core/instance/events.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/vue/src/core/instance/events.js')
-rw-r--r--node_modules/vue/src/core/instance/events.js142
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
+ }
+}