全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

深入理解Vue.js源码之事件机制

写在前面

因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出。

文章的原地址:https://github.com/answershuto/learnVue。

在学习过程中,为Vue加上了中文的注释https://github.com/answershuto/learnVue/tree/master/vue-src,希望可以对其他想学习Vue源码的小伙伴有所帮助。
可能会有理解存在偏差的地方,欢迎提issue指出,共同学习,共同进步。

Vue事件API

众所周知,Vue.js为我们提供了四个事件API,分别是$on](https://cn.vuejs.org/v2/api/#vm-on-event-callback),[$once,$off](https://cn.vuejs.org/v2/api/#vm-off-event-callback),[$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用来移除自定义事件

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
  /*如果event是数组则递归注销事件*/
  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]
  /*Github:https://github.com/answershuto*/
  /*本身不存在该事件则直接返回*/
  if (!cbs) {
   return vm
  }
  /*如果只传了event参数则注销该event方法下的所有方法*/
  if (arguments.length === 1) {
   vm._events[event] = null
   return vm
  }
  // 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
 }

$emit

$emit用来触发指定的自定义事件。

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++) {
    cbs[i].apply(vm, args)
   }
  }
  return vm
 }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# Vue.js  # 事件机制  # 浅谈Vue2.0父子组件间事件派发机制  # 一篇文章带你了解vue.js的事件循环机制  # vue @click与@click.native  # 及vue事件机制的使用分析  # 递归  # 自定义  # 遍历  # 而不  # 这样做  # 方法来  # 创建一个  # 移除  # 可以减少  # 是个  # 会有  # 也就  # 上了  # 感兴趣  # 对其  # 不存在  # 花了  # 他想  # 这几个  # 转换成 


相关文章: Android自定义控件实现温度旋转按钮效果  北京网站制作公司哪家好一点,北京租房网站有哪些?  ,购物网站怎么盈利呢?  已有域名和空间,如何快速搭建网站?  常州企业网站制作公司,全国继续教育网怎么登录?  专业网站制作服务公司,有哪些网站可以免费发布招聘信息?  ,怎么用自己头像做动态表情包?  北京专业网站制作设计师招聘,北京白云观官方网站?  早安海报制作网站推荐大全,企业早安海报怎么每天更换?  如何设置并定期更换建站之星安全管理员密码?  智能起名网站制作软件有哪些,制作logo的软件?  洛阳网站制作公司有哪些,洛阳的招聘网站都有哪些?  C++如何使用std::optional?(处理可选值)  制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?  建站之星如何取消后台验证码生成?  相亲简历制作网站推荐大全,新相亲大会主持人小萍萍资料?  香港服务器选型指南:免备案配置与高效建站方案解析  在线教育网站制作平台,山西立德教育官网?  台州网站建设制作公司,浙江手机无犯罪记录证明怎么开?  成都网站制作价格表,现在成都广电的单独网络宽带有多少的,资费是什么情况呢?  网站制作知乎推荐,想做自己的网站用什么工具比较好?  郑州企业网站制作公司,郑州招聘网站有哪些?  建站之星会员如何解锁更多建站功能?  图册素材网站设计制作软件,图册的导出方式有几种?  如何在IIS中配置站点IP、端口及主机头?  如何在香港服务器上快速搭建免备案网站?  大连网站设计制作招聘信息,大连投诉网站有哪些?  C++中的Pimpl idiom是什么,有什么好处?(隐藏实现)  详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)  三星网站视频制作教程下载,三星w23网页如何全屏?  如何在Ubuntu系统下快速搭建WordPress个人网站?  如何通过VPS建站实现广告与增值服务盈利?  如何快速登录WAP自助建站平台?  宝塔新建站点为何无法访问?如何排查?  制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?  企业网站制作费用多少,企业网站空间一般需要多大,费用是多少?  小捣蛋自助建站系统:数据分析与安全设置双核驱动网站优化  如何规划企业建站流程的关键步骤?  制作网站的软件下载免费,今日头条开宝箱老是需要下载怎么回事?  无锡营销型网站制作公司,无锡网选车牌流程?  建站之星×万网:智能建站系统+自助建站平台一键生成  如何彻底删除建站之星生成的Banner?  制作网站哪家好,cc、.co、.cm哪个域名更适合做网站?  建站主机是什么?如何选择适合的建站主机?  如何通过网站建站时间优化SEO与用户体验?  如何快速搭建二级域名独立网站?  如何在阿里云香港服务器快速搭建网站?  网站视频怎么制作,哪个网站可以免费收看好莱坞经典大片?  在线制作视频网站免费,都有哪些好的动漫网站?  关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework) 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。