[Vue源码解析] 事件相关的实例方法

14 篇文章 0 订阅
本文详细解析了Vue框架中与事件相关的实例方法,包括$on、$off、$once和$emit的实现原理。$on用于添加事件监听器,支持数组形式的事件名;$off用于移除监听器,可以按需移除全部或指定事件的监听器;$once则实现了只触发一次的监听器,触发后自动移除;$emit用于触发实例上的事件,并传递参数给监听器。这些方法都是基于Vue实例的_events属性进行操作的。
摘要由CSDN通过智能技术生成

[Vue源码解析] 事件相关的实例方法

在Vue中有五个重要的函数用来向Vue的原型中挂载方法:

initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)

在initMixin中会向Vue构造函数的prototype属性添加_init方法,执行new Vue()时,会调用_init方法来实现一系列初始化操作,包括整个生命周期的流程以及响应式系统流程的启动等。

在stateMixin中向Vue原型上挂载了vm. w a t c h , v m . watch,vm. watch,vm.set,vm.$delete这三个与数据相关的实例方法

在eventsMixin中挂载了四个与事件相关的实例方法:vm. o n 、 v m . on、vm. onvm.once、vm. o f f 、 v m . off、vm. offvm.emit

首先要说明一个属性:vm._events,此属性是在new Vue的时候调用_init方法挂载的vm._events = Object.create(null),该属性用来存储事件。

1、vm.$on(event, callback)

/**
 * vm.$on源码
 * @param {*} event 
 * @param {*} fn 
 */
Vue.prototype.$on = function (event, fn) {
  const vm = 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)
    return vm
  }
}

理解:传入一个事件和回调函数,如果事件是一个事件数组,则递归调用,如果不是则在vm._events上挂载该事件(key)的回调函数(value)

2、vm.$off([event, callback])

  • 用法:

    1. 如果没有提供参数,则移除所有事件的监听器

    2. 提供了事件,移除该事件对应的所有监听器

    3. 同时提供了事件与回调,则只移除这个回调的监听器

/**
 * vm.$off源码
 */

 Vue.prototype.$on = function (event, fn) {
   const vm = this
   //没有参数移除所用监听器
   if (!arguments.length) {
     vm._events = Object.create(null)
     return vm
   }

   //event支持数组
   if (Array.isArray(event)) {
     for (let i = 0, l = event.length; i < 1; i++) {
       this.$off(event[i], fn)
     }
     return vm
   }
   //取出对应的监听器
   const cbs = vm._events[event]
   if (!cbs) {
     return vm
   }

   //没有fn参数时移除该事件的所用监听器
   if (arguments.length === 1) {
     vm._events = null
     return vm
   }

   //有fn参数时只移除与fn相同的监听器
   if (fn) {
     let cb
     let i = cbs.length
     while (i--) {
       cb = cbs[i]
       if (cb === fn || cb.fn === fn) {
         cbs.splice(i, 1)
         break
       }
     }
   }
   return vm
 }

3、vm.$once(event, callback)

用法:监听一个自定义事件,但是只触发一次,在第一次触发后移除监听器

 /**
  * vm.$once源码
  */

Vue.prototype.$once = function (event, fn) {
  const vm = this
  function on () {
    vm.$off(event, on)
    fn.apply(vm, arguments)
  }
  on.fn = fn
  vm.$on(event, on)
  return vm
}

理解:很清晰, o n c e 注 册 监 听 器 其 实 使 用 once注册监听器其实使用 once使on注册的,而且注册的函数是我们自定义的函数,触发事件时会先摘除该事件监听器,然后执行原来的回调函数

4、vm.$emit(event, […args])

用法:触发当前实例上的事件,附加参数都会传给监听器回调

/**
 * vm.$emit
 */


Vue.prototype.$emit = function (event) {
  const vm = this
  let cbs = vm._events[event]
  if (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
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值