初探 Vue 生命周期和钩子函数
生命周期
生命周期函數就是 Vue 實例在某一個時間點會自動執行的函數。
簡單來說就是好像把人的出生到死亡分成一個個階段,你取名字肯定是在你出生階段,而不是在成年階段;你結婚肯定是在成年階段,而不是在出生階段;如果說你在出生階段想去階段,那肯定是不行的。
組件也是一樣,在實例化的時特定階段調用特定方法,調用的這個方法就是鉤子函數。
鉤子函數
鉤子函數和回調函數有什么區別嗎?
它們區別是:
js派函數監聽事件 => 監聽函數就是所謂的鉤子函數 => 函數鉤取事件:函數主動找事件 => 鉤子函數js預留函數給dom事件,dom事件調用js預留的函數 => 事件派發給函數:事件調用函數 => 回調函數
打個比方:
鉤子函數:一個房間里的監控攝像頭監控著每一個進入的人的面部特征,識別出了符合條件的人就觸發警告(執行函數事件);回調函數:可以看做是在一片地區埋了許許多多的地雷,一旦踩中了某個地雷(觸發事件),地雷就會爆炸(執行函數事件)。
可以簡單的理解為:
鉤子函數是事件被動的監聽,一旦條件觸發就執行回調函數是主動事件,執行函數體內容
生命周期探究
<template><div>{{msg}}</div> </template><script> export default {name: 'HelloWorld',data () {return {msg: 'hello world',msg1: ''}},beforeCreate () {console.groupCollapsed('beforeCreate 創建前狀態')console.log('%c%s', 'color:MediumVioletRed', 'el : ' + this.$el)console.log(this.$el)console.log('%c%s', 'color:MediumVioletRed', 'data : ' + this.$data)console.log(this.$data)console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)console.groupEnd()},created () {console.groupCollapsed('created 創建前狀態')console.log('%c%s', 'color:MediumVioletRed', 'el : ' + this.$el)console.log(this.$el)console.log('%c%s', 'color:MediumVioletRed', 'data : ' + this.$data)console.log(this.$data.msg)console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)console.groupEnd()},beforeMount () {console.groupCollapsed('beforeMount 掛載前狀態')console.log('%c%s', 'color:MediumVioletRed', 'el : ' + this.$el)console.log(this.$el)console.log('%c%s', 'color:MediumVioletRed', 'data : ' + this.$data)console.log(this.$data.msg)console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)console.groupEnd()},mounted () {console.groupCollapsed('mounted 掛載后狀態')console.log('%c%s', 'color:MediumVioletRed', 'el : ' + this.$el)console.log(this.$el)console.log('%c%s', 'color:MediumVioletRed', 'data : ' + this.$data)console.log(this.$data.msg)console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)console.groupEnd()setTimeout(() => {this.$data.msg = '123'}, 5000)},activated () {console.groupCollapsed('activated 掛載后狀態')console.log('%c%s', 'color:MediumVioletRed', 'el : ' + this.$el)console.log(this.$el)console.log('%c%s', 'color:MediumVioletRed', 'data : ' + this.$data)console.log(this.$data.msg)console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)console.groupEnd()setTimeout(() => {this.$data.msg = 'hello tiantian'}, 10000)},beforeUpdate () {console.groupCollapsed('beforeUpdate 更新前狀態')console.log('%c%s', 'color:MediumVioletRed', 'el : ' + this.$el)console.log(this.$el)console.log('%c%s', 'color:MediumVioletRed', 'data : ' + this.$data)console.log(document.getElementById('app').innerHTML)console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)console.groupEnd()},updated () {console.groupCollapsed('updated 更新后狀態')console.log('%c%s', 'color:MediumVioletRed', 'el : ' + this.$el)console.log(this.$el)console.log('%c%s', 'color:MediumVioletRed', 'data : ' + this.$data)console.log(document.getElementById('app').innerHTML)console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)console.groupEnd()setTimeout(() => {this.$destroy()}, 5000)},beforeDestroy () {console.groupCollapsed('beforeDestroy 實例銷毀前狀態')console.log('%c%s', 'color:MediumVioletRed', 'el : ' + this.$el)console.log(this.$el)console.log('%c%s', 'color:MediumVioletRed', 'data : ' + this.$data)console.log(document.getElementById('app').innerHTML)console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)console.groupEnd()},destroyed () {console.groupCollapsed('destroyed 實例銷毀后狀態')console.log('%c%s', 'color:MediumVioletRed', 'el : ' + this.$el)console.log(this.$el)console.log('%c%s', 'color:MediumVioletRed', 'data : ' + this.$data)console.log(document.getElementById('app').innerHTML)console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)console.groupEnd()} } </script>
beforeCreate和created
beforeCreate:在實例初始化完成時,被執行created:在初始化結束之后會再初始化一些外部注入和一些雙向綁定相關的事情時,被執行
這兩個鉤子函數執行完之后,初始化基本完成了。
在beforeCreate階段,el和data都沒有被掛載;而在created階段,el還沒被掛在,但data已經被掛載了,如下圖所示:
這里el為啥沒有被掛載呢?
看上圖,在created執行完畢后,它會詢問一個條件:你這個Vue實例里是否有el這個選項。
如果有就又會詢問是否有template這個選項:
-
如果沒有template就會走右側的分支,
- 如果這個實例沒有template,就會將el這個根節點當做模版,來進行渲染
-
如果有template就會走左側的分支
- 把template作為模版去渲染
beforeMount和mounted
beforeMount:執行時,頁面還沒有被渲染mounted:執行時,頁面已經被渲染了
從圖中也可以看出,在beforeMount執行時,el還沒有被掛在;當mounted執行時,el被掛載到頁面了。
beforeUpdate和updated
beforeUpdate:數據被改變,還沒渲染之前會被執行updated:數據被改變,渲染完成后會被執行
這張圖中有個奇怪的現象,為什么在beforeUpdate和updated兩個鉤子函數中,el和msg都是一樣呢?beforeUpdate執行是不應該是老數據嘛,怎么這里也是最新的數據了?
因為這里的el是虛擬dom,不是真實的dom,和data都是對象,在加上console.log這里是個異步操作,當你點開console.log時,其實代碼早就跑完了,數據已經是最新的了,所以就會看到在這兩個函數中輸出結果是一樣的了。
可以用document.getElementById('app').innerHTML獲取真實的Dom結構,這時我們就可以看到這兩處不一樣的地方了。
beforeDestroy和destroyed
調用vm.$destroy()方法可對實例銷毀
beforeDestroy:實例被銷毀前被執行destroyed:實例被銷毀后被執行
activated和deactivated
使用keep-alive標簽后,會有兩個生命周期函數分別是:activated、deactivated
activated:頁面展示的時候被執行deactivated:頁面被隱藏或者頁面即將被替換成新的頁面時被執行
總結
created:掛載之前需要做的一些事情可以在放在這里面,比如頁面加載時loading動畫
mounted:向后端發請求,可以放在這個函數中。
這兩個鉤子函數使用時機重疊部分很多,反正是怎么方便怎么來就是了。
參考資源
總結
以上是生活随笔為你收集整理的初探 Vue 生命周期和钩子函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 透过 OKR 进行项目过程管理
- 下一篇: 4.36域名重定向4.37用户认证4.3