首先我们打开'src/core/instance/events.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.$options._parentListeners'父组件传递过来的事件,如果存在就调用‘updateComponentListeners’函数。
updateComponentListeners函数代码如下:
export function updateComponentListeners ( vm: Component, listeners: Object, oldListeners: ?Object) { target = vm updateListeners(listeners, oldListeners || {}, add, remove, createOnceHandler, vm) target = undefined}
可以看到这个函数就3行代码。
1、设置target为vm
2、调用updateListeners函数
3、清空target的值
updateListeners函数代码如下:
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) } }}
首先我们先看大致罗列一下此函数的作用:
1、获取新旧事件
2、处理事件的修饰符
3、创建事件调用函数
4、添加为自定义事件
5、销毁旧的事件
接下来我们来慢慢拆分一下这个函数功能。
def = cur = on[name] old = oldOn[name] event = normalizeEvent(name)
‘cur’变量获取当前的事件,‘old’变量获取旧的事件。
‘normalizeEvent’处理当前事件修饰符
有如下三个修饰符:
1、capture 添加事件侦听器时使用 capture 模式
2、once 只触发一次回调
3、passive 以 { passive: true } 模式添加侦听器
if (isUndef(cur.fns)) { cur = on[name] = createFnInvoker(cur, vm) }
如果当前事件没有'fns'属性,则创建调用函数(createFnInvoker)。
createFnInvoker代码如下:
export function createFnInvoker (fns: Function | Array, vm: ?Component): Function { function invoker () { const fns = invoker.fns if (Array.isArray(fns)) { const cloned = fns.slice() for (let i = 0; i < cloned.length; i++) { invokeWithErrorHandling(cloned[i], null, arguments, vm, `v-on handler`) } } else { // return handler return value for single handlers return invokeWithErrorHandling(fns, null, arguments, vm, `v-on handler`) } } invoker.fns = fns return invoker}
可以看到定义了一个 ‘invoker’ 函数,然后给函数添加了 'fns'属性,然后 直接返回了该函数。
if (isTrue(event.once)) { cur = on[name] = createOnceHandler(event.name, cur, event.capture)}
如果事件存在 'once' 修饰符,则调用 ‘createOnceHandler’ 函数。
createOnceHandler代码如下:
function createOnceHandler (event, fn) { const _target = target return function onceHandler () { const res = fn.apply(null, arguments) if (res !== null) { _target.$off(event, onceHandler) } }}
可以看到直接返回了一个函数,这个函数被调用之后会调用 '$off'进行事件关闭。
add(event.name, cur, event.capture, event.passive, event.params)// add函数代码如下function add (event, fn) { target.$on(event, fn)}
调用add函数,注册自定义事件。
for (name in oldOn) { if (isUndef(on[name])) { event = normalizeEvent(name) remove(event.name, oldOn[name], event.capture) } }
最后是对旧的事件进行关闭操作(remove函数)。
remove函数代码:
function remove (event, fn) { target.$off(event, fn)}