若是咱們想要從父組件獲取子組件的生命週期,除了在子組件相應的生命週期內部向父組件通訊這種作法以外,還能夠使用生命週期鉤子。vue
<template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <HelloWorld @hook:beforeCreate="console('child: beforeCreate')" @hook:created="console('child: created')" @hook:beforeMount="console('child: beforeMount')" @hook:mounted="console('child: mounted')" @hook:beforeUpdate="console('child: beforeUpdate')" @hook:updated="console('child: updated')" @hook:beforeDestroy="console('child: beforeDestroy')" @hook:destroyed="console('child: destroyed')" msg="Welcome to Your Vue.js App" /> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'App', components: { HelloWorld }, methods: { console(str) { console.log(str); }, }, beforeCreate() { console.log('parent: beforeCreate'); }, created() { console.log('parent: created'); }, beforeMount() { console.log('parent: beforeMount'); }, mounted() { console.log('parent: mounted'); }, beforeUpdate() { console.log('parent: beforeUpdate'); }, updated() { console.log('parent: updated'); }, beforeDestroy() { console.log('parent: beforeDestroy'); }, destroyed() { console.log('parent: destroyed'); }, } </script>
控制檯打印以下:app
parent: beforeCreate parent: created parent: beforeMount child: beforeCreate child: created child: beforeMount child: mounted parent: mounted parent: beforeUpdate child: beforeUpdate child: updated parent: updated parent: beforeDestroy child: beforeDestroy child: destroyed parent: destroyed
// init.js export function initMixin (Vue: Class<Component>) { Vue.prototype._init = function (options?: Object) { const vm: Component = this // a uid vm._uid = uid++ let startTag, endTag /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production' && config.performance && mark) { startTag = `vue-perf-start:${vm._uid}` endTag = `vue-perf-end:${vm._uid}` mark(startTag) } // a flag to avoid this being observed vm._isVue = true // merge options if (options && options._isComponent) { // optimize internal component instantiation // since dynamic options merging is pretty slow, and none of the // internal component options needs special treatment. initInternalComponent(vm, options) } else { vm.$options = mergeOptions( resolveConstructorOptions(vm.constructor), options || {}, vm ) } /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { initProxy(vm) } else { vm._renderProxy = vm } // expose real self vm._self = vm initLifecycle(vm) initEvents(vm) initRender(vm) callHook(vm, 'beforeCreate') initInjections(vm) // resolve injections before data/props initState(vm) initProvide(vm) // resolve provide after data/props callHook(vm, 'created') /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production' && config.performance && mark) { vm._name = formatComponentName(vm, false) mark(endTag) measure(`vue ${vm._name} init`, startTag, endTag) } if (vm.$options.el) { vm.$mount(vm.$options.el) } } } // lifecycle.js export function callHook (vm: Component, hook: string) { // #7573 disable dep collection when invoking lifecycle hooks pushTarget() const handlers = vm.$options[hook] const info = `${hook} hook` if (handlers) { for (let i = 0, j = handlers.length; i < j; i++) { invokeWithErrorHandling(handlers[i], vm, null, vm, info) } } if (vm._hasHookEvent) { vm.$emit('hook:' + hook) } popTarget() }
能夠看到,每次觸發鉤子的時候是經過 callHook 進行觸發的,而 callHook 裏面會 emit 這個生命週期的鉤子。ide
能夠看到,前面會判斷 _hasHookEvent ,這是幹嗎的?源碼以下:ui
// 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) } } 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++) { vm.$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 } // ... }
能夠看到,在初始化事件的時候,會將 _hasHookEvent 設置爲false,而後在$on
方法裏面判斷是否有 hook 鉤子,有的話就把 _hasHookEvent 設置爲 true。咱們在子組件上綁定了 hook 鉤子,因此其內部會調用這個$on
方法把 _hasHookEvent 設置爲 true,從而發出生命週期鉤子事件。this
我猜這個是遺留代碼,目前已經沒什麼用了的緣由。。。。prototype