HookEvent
源码地址:https://github.com/vuejs/vue/blob/master/src/core/instance/lifecycle.js#L314
export function callHook (vm: Component, hook: string) {
const handlers = vm.$options[hook]
if (handlers) {
for (let i = 0, j = handlers.length; i < j; i++) {
try {
handlers[i].call(vm)
} catch (e) {
handleError(e, vm, `${hook} hook`)
}
}
}
if (vm._hasHookEvent) {
vm.$emit('hook:' + hook)
}
}
- 对外的生命周期函数需要主动捕获其过程发生的错误,避免整个Vue实例生成过程终止
- 生命周期函数存放位置
const handlers = vm.$options[hook]
- 可以通过
$on
进行监听事件vm.$emit('hook:' + hook)
vm._hasHookEvent
- 初始化事件相关
initEvents
函数中赋值为 false - 事件注册实例方法
$on
中赋值为 true callHoook
函数中判断_hasHookEvent
是否为true
源码地址:https://github.com/vuejs/vue/blob/master/src/core/instance/events.js#L52
export function eventsMixin (Vue: Class<Component>) {
const hookRE = /^hook:/
Vue.prototype.$on = function (event: string | Array<string>, 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
}
const hookRE = /^hook:/
注册事件以 hook:
开头
实现方式
常规方式
子组件修改;
mounted() {
this.$emit("mounted");
}
父组件中调用:
<Child @mounted="doSomething"></Child>
缺点: 需要修改子组件源码,增加相关 $emit
事件
$options方式
通过 refs 获取相关组件实例,然后增加相应的 lifecycle hook
mounted () {
const HelloWorldVmOption = this.$refs['HelloWorldRef'].$options
if (!HelloWorldVmOption['updated']) HelloWorldVmOption['updated'] = []
HelloWorldVmOption['updated'].push(() => {
...
})
}
缺点: 由于 refs 只能在 mounted 及以后的生命周期中获取,因此这种方式只能监听子组件 mounted
以后的 lifecycle hook。
@hook:event
<Child @hook:mounted="doSomething"></Child>
在 vue2 中,完美解决!不需要修改源码~~