源码地址: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)
}
}
const handlers = vm.$options[hook]
vm._hasHookEvent
initEvents
函数中赋值为 false$on
中赋值为 truecallHoook
函数中判断_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
事件
通过 refs 获取相关组件实例,然后增加相应的 lifecycle hook
mounted () {
const HelloWorldVmOption = this.$refs['HelloWorldRef'].$options
if (!HelloWorldVmOption['updated']) HelloWorldVmOption['updated'] = []
HelloWorldVmOption['updated'].push(() => {
...
})
}
缺点: 由于 refs 只能在 mounted 及以后的生命周期中获取,因此这种方式只能监听子组件 mounted
以后的 lifecycle hook。
<Child @hook:mounted="doSomething">Child>
在 vue2 中,完美解决!不需要修改源码~~