Vue源码分析之事件机制

·  阅读 84

这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战

前言

前边看了Vue在初始化过程中是如何初始化生命周期的,这篇来看下对于事件这块,Vue是怎么处理的,除了初始化以外,还可以学习下整个Vue对事件机制的实现。

首先来看下初始化事件函数:

initEvents

initEvents定义在src/core/instance/event.js中

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)
  }
}
复制代码
  • 初始化vm实例的_events和_hasHookEvent变量值。

  • 当定义了与父组件相关的事件,会执行updateComponetListeners去初始化与父组件关联的事件。

看一下这个updateComponentListeners做了什么:

export function updateComponentListeners (
  vm: Component,
  listeners: Object,
  oldListeners: ?Object
) {
  target = vm
  updateListeners(listeners, oldListeners || {}, add, remove, createOnceHandler, vm)
  target = undefined
}
复制代码

updateComponentListeners内部主要是调用了updateListeners方法。

updateListeners

updateListeners定义在src/core/vdom/helpers/update-listeners.js中。

export function updateListeners (
  on: Object,
  oldOn: Object,
  add: Function,
  remove: Function,
  createOnceHandler: Function,
  vm: Component
) {
  let name, def, cur, old, event
  for (name in on) {
    def = cur = on[name]
    old = oldOn[name]
    event = normalizeEvent(name)
    /* istanbul ignore if */
    if (__WEEX__ && isPlainObject(def)) {
      cur = def.handler
      event.params = def.params
    }
    if (isUndef(cur)) {
      process.env.NODE_ENV !== 'production' && warn(
        `Invalid handler for event "${event.name}": got ` + String(cur),
        vm
      )
    } else if (isUndef(old)) {
      if (isUndef(cur.fns)) {
        cur = on[name] = createFnInvoker(cur, vm)
      }
      if (isTrue(event.once)) {
        cur = on[name] = createOnceHandler(event.name, cur, event.capture)
      }
      add(event.name, cur, event.capture, event.passive, event.params)
    } else if (cur !== old) {
      old.fns = cur
      on[name] = old
    }
  }
  for (name in oldOn) {
    if (isUndef(on[name])) {
      event = normalizeEvent(name)
      remove(event.name, oldOn[name], event.capture)
    }
  }
}
复制代码

updateListeners接收六个参数:

  • on:所有要绑定的事件回调函数对象

  • oldOn:旧的事件回调函数对象

  • add:增加事件函数

  • remove:移除事件函数

  • createOnceHandler:创建仅执行一次事件的 句柄函数

  • vm:当前Vue实例

总体来看,该函数就是对比新老listeners对象,通过add和remove函数去增加和移除对应的事件,接下来具体看下函数内部做了什么:

1. 首先遍历on对象,取出新老回调函数,这里对每一项执行了normalizeEvent方法,来看下这个方法。

normalizeEvent

const normalizeEvent = cached((name: string): {
  name: string,
  once: boolean,
  capture: boolean,
  passive: boolean,
  handler?: Function,
  params?: Array<any>
} => {
  const passive = name.charAt(0) === '&'
  name = passive ? name.slice(1) : name
  const once = name.charAt(0) === '~' // Prefixed last, checked first
  name = once ? name.slice(1) : name
  const capture = name.charAt(0) === '!'
  name = capture ? name.slice(1) : name
  return {
    name,
    once,
    capture,
    passive
  }
})
复制代码

看到这个函数的返回值once,capture,passive是不是很属性,这不就是事件修饰符

image.png

总体来说normalizeEvent函数就是通过解析字符串来规范化事件名称,将事件前缀拿出来,并将对应的修饰符置为true。继续看updateListeners方法~

分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改