事件机制是Vue中重要的通信机制,这里看下源码简单说明下Vue事件emit和on的实现:
$on和$emit函数的实现:
```Vue.prototype.$on = function (event: string | Array, fn: Function): Component {
const vm: Component = 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)
// optimize hook:event cost by using a boolean flag marked at registration
// instead of a hash lookup
if (hookRE.test(event)) {
vm._hasHookEvent = true
}
}
return vm
}
```
很简单,就是创建一个event数组成员,保存定义的事件名称和处理函数,数组的下标就是时间的名称,value是函数引用。但是要注意,时间都是保存在当前对象上的,比如new了一个组件的实例A,在A上注册的事件,是在A的_event数组中保存。
```Vue.prototype.$emit = function (event: string): Component {
const vm: Component = this
... 省略不重要代码
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++) {
try {
cbs[i].apply(vm, args)
} catch (e) {
handleError(e, vm, `event handler for "${event}"`)
}
}
}
return vm
}
}
```
这个函数也很简单,emit直接调用了注册在本组件上的响应函数。**但是,这是问题的全部么?**,比如组件B上emit了一个事件,而这个事件注册在组件A上,这时候,必须执行A上的emit才可以完成整个事件流程,那这又是在哪里实现的呢?
仔细回忆了下emit和on的使用:
1. 父子组件通信,子组件可以emit然后修改父组件的data来实现通讯,这里on和emit都在子组件上,注意不是子组件emit父组件on,而是都在子组件上。
2. 组件之间通信,使用专门的通信组件bus,此时,on和emit都在Vue的实例bus上调用。
所以emit和on都是在同一个实例上调用的,上面的代码**That’s all**。