D86ebd4f9cf2a301feedd5a8085695bc
Vue.js 源码——事件机制

Vue事件API

众所周知,Vue.js为我们提供了四个事件API,分别是$on$once$off$emit

初始化事件

初始化事件在vm上创建一个_events对象,用来存放事件。_events的内容如下:

  • {
  • eventName: [func1, func2, func3]
  • }

存放事件名以及对应执行方法。

  • /*初始化事件*/
  • export function initEvents (vm: Component) {
  • /*在vm上创建一个_events对象,用来存放事件。*/
  • vm._events = Object.create(null)
  • /*这个bool标志位来表明是否存在钩子,而不需要通过哈希表的方法来查找是否有钩子,这样做可以减少不必要的开销,优化性能。*/
  • vm._hasHookEvent = false
  • // init parent attached events
  • /*初始化父组件attach的事件*/
  • const listeners = vm.$options._parentListeners
  • if (listeners) {
  • updateComponentListeners(vm, listeners)
  • }
  • }

$on

$on方法用来在vm实例上监听一个自定义事件,该事件可用$emit触发。

  • Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component {
  • const vm: Component = this
  • /*如果是数组的时候,则递归$on,为每一个成员都绑定上方法*/
  • 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
  • /*这里在注册事件的时候标记bool值也就是个标志位来表明存在钩子,而不需要通过哈希表的方法来查找是否有钩子,这样做可以减少不必要的开销,优化性能。*/
  • if (hookRE.test(event)) {
  • vm._hasHookEvent = true
  • }
  • }
  • return vm
  • }

$once

$once监听一个只能触发一次的事件,在触发以后会自动移除该事件。

  • 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
  • }

$off

$off用来移除自定义事件

top Created with Sketch.