一、生命周期
生命周期是指vue實例從創建到銷毀所經歷的一系列過程。vue官網生命周期如下圖所示:

上圖一共描述了8個生命周期鈎子函數,即:
'beforeCreate', 'created', 'beforeMount', 'mounted', 'beforeUpdate', 'updated', 'beforeDestroy', 'destroyed',
思考一個問題,vue實例中一共就這8個生命周期鈎子函數嗎?
答案是,vue生命周期鈎子函數不止這8個。
(1)動態組件鈎子函數
vue實例若是動態組件(即keep-alive)時,還有2個鈎子函數:
'activated',
'deactivated',
(2)errorCaptured
errorCaptured是vue 2.5.0版本新增的一個鈎子函數,它主要用來捕獲一個來自子孫組件的錯誤,即可以應用在前端監控中。
結論:vue一共有11個說明周期鈎子函數。
二、父組件如何監聽子組件生命周期鈎子函數
1、使用$on和$emit
子組件$emit觸發一個事件,父組件$on監聽相應事件。
// Parent.vue
<Child @mounted="doSomething"/>
// Child.vue
mounted() { this.$emit("mounted"); }
2、hook鈎子函數
使用vue hook生命周期鈎子函數。
// Parent.vue
<Child @hook:mounted="doSomething" ></Child>
doSomething() { console.log('父組件監聽到 mounted 鈎子函數 ...'); }, // Child.vue
mounted(){ console.log('子組件觸發 mounted 鈎子函數 ...'); }, // 以上輸出順序為: // 子組件觸發 mounted 鈎子函數 ... // 父組件監聽到 mounted 鈎子函數 ...
下面闡述vue hook生命周期原理:
(1)vue源碼生命周期描述
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')
即生命周期鈎子函數(如beforeCreate、created等)都會調用callHook函數。
(2)callHook函數源碼
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() }
即每個生命周期鈎子函數執行函數為:vm.$emit('hook:' + hook),前提條件是_hasHookEvent值為true。
(3)_hasHookEvent標志位源碼
const hookRE = /^hook:/ // 以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 }
當使用了$on方法監聽事件時,如果事件名以 hooks: 作為前綴,那么這個事件會被當做hookEvent,注冊事件回調的同時,vm._hasHookEvent會被置為true。當使用callHook調用生命周期函數時,由於_hasHookEvent為true,所以會$emit('hooks:xxx'),注冊的生命周期函數就會執行。
三、生命周期鈎子函數調用方法匯總
(1)在Vue組件選項中添加鈎子函數
<script> export default { components: {}, data () { return { } }, computed: { }, created () { }, mounted () { }, beforeDestroy () {} } </script>
(2)在模板中添加@hooks:created
// Parent.vue <Child @hook:mounted="doSomething" ></Child>
(3)js代碼
vm.$on('hooks:created', cb);
vm.$once('hooks:created', cb);//只執行一次
