前言
在使用vue開發(fā)的過程中宫补,我們經(jīng)常會接觸到生命周期的問題禽炬。那么你知道,一個標準的工程項目中蟹瘾,會有多少個生命周期勾子嗎圾浅?讓我們來一起來盤點一下:
根組件實例:8個 (beforeCreate、created憾朴、beforeMount狸捕、mounted、beforeUpdate伊脓、updated府寒、beforeDestroy、destroyed)
組件實例:8個 (beforeCreate报腔、created、beforeMount剖淀、mounted纯蛾、beforeUpdate、updated纵隔、beforeDestroy翻诉、destroyed)
全局路由鉤子:2個 (beforeEach、afterEach)
組件路由鉤子:3個 (beforeRouteEnter捌刮、beforeRouteUpdate碰煌、beforeRouteLeave)
指令的周期: 5個 (bind、inserted绅作、update芦圾、componentUpdated、unbind)
beforeRouteEnter的next所對應的周期
nextTick所對應的周期
嚇到了嗎俄认?合計竟然一共有28個周期个少,是否看得頭昏眼花了呢?接下來讓我們一起來介紹一下各個周期的通常用途與使用細節(jié)吧
組件實例周期
這一塊vue2的官方文檔有一張圖示眯杏,我們簡要提一下用法和注意
beforeCreate
在實例初始化之后夜焦,數(shù)據(jù)觀測(data observer) 和 event/watcher 事件配置之前被調(diào)用。
tip:此時組件的選項還未掛載岂贩,因此無法訪問methods茫经,data,computed上的方法或數(shù)據(jù)
created
實例已經(jīng)創(chuàng)建完成之后被調(diào)用。在這一步,實例已完成以下的配置:數(shù)據(jù)觀測(data observer)卸伞,屬性和方法的運算褥紫, watch/event 事件回調(diào)。然而瞪慧,掛載階段還沒開始髓考,$el 屬性目前不可見。
這是一個常用的生命周期弃酌,因為你可以調(diào)用methods中的方法氨菇、改變data中的數(shù)據(jù),并且修改可以通過vue的響應式綁定體現(xiàn)在頁面上妓湘、獲取computed中的計算屬性等等查蓉。
tip:通常我們可以在這里對實例進行預處理。也有一些童鞋喜歡在這里發(fā)ajax請求榜贴,值得注意的是豌研,這個周期中是沒有什么方法來對實例化過程進行攔截的。因此假如有某些數(shù)據(jù)必須獲取才允許進入頁面的話唬党,并不適合在這個頁面發(fā)請求鹃共。建議在組件路由勾子beforeRouteEnter中來完成。
beforeMonut
在掛載開始之前被調(diào)用:相關(guān)的 render 函數(shù)首次被調(diào)用驶拱。
mounted
el 被新創(chuàng)建的 vm.$el 替換霜浴,并掛載到實例上去之后調(diào)用該鉤子。如果 root 實例掛載了一個文檔內(nèi)元素蓝纲,當 mounted 被調(diào)用時 vm.$el 也在文檔內(nèi)阴孟。
tip:1.在這個周期內(nèi),對data的改變可以生效税迷。但是要進下一輪的dom更新永丝,dom上的數(shù)據(jù)才會更新。2.這個周期可以獲取 dom箭养。 之前的論斷有誤慕嚷,感謝@馮銀超 和@AnHour的提醒3.beforeRouteEnter的next的勾子比mounted觸發(fā)還要靠后4.指令的生效在mounted周期之前
beforeUpdate
數(shù)據(jù)更新時調(diào)用,發(fā)生在虛擬 DOM 重新渲染和打補丁之前露懒。你可以在這個鉤子中進一步地更改狀態(tài)闯冷,這不會觸發(fā)附加的重渲染過程。
updated
由于數(shù)據(jù)更改導致的虛擬 DOM 重新渲染和打補丁懈词,在這之后會調(diào)用該鉤子蛇耀。當這個鉤子被調(diào)用時,組件 DOM 已經(jīng)更新坎弯,所以你現(xiàn)在可以執(zhí)行依賴于 DOM 的操作纺涤。然而在大多數(shù)情況下译暂,你應該避免在此期間更改狀態(tài),因為這可能會導致更新無限循環(huán)撩炊。
beforeDestroy
實例銷毀之前調(diào)用外永。在這一步,實例仍然完全可用拧咳。
tip:1.這一步還可以用this來獲取實例伯顶。2.一般在這一步做一些重置的操作。比如清除掉組件中的 定時器 和 監(jiān)聽的dom事件
destroyed
Vue 實例銷毀后調(diào)用骆膝。調(diào)用后祭衩,Vue 實例指示的所有東西都會解綁定,所有的事件監(jiān)聽器會被移除阅签,所有的子實例也會被銷毀掐暮。
全局路由鉤子
作用于所有路由切換,一般在main.js里面定義
router.beforeEach
示例router.beforeEach((to,from,next)=>{? console.log('路由全局勾子:beforeEach -- 有next方法')next()})
一般在這個勾子的回調(diào)中政钟,對路由進行攔截路克。
比如,未登錄的用戶养交,直接進入了需要登錄才可見的頁面精算,那么可以用next(false)來攔截,使其跳回原頁面层坠。
值得注意的是殖妇,如果沒有調(diào)用next方法,那么頁面將卡在那破花。
next的四種用法1.next() 跳入下一個頁面2.next('/path') 改變路由的跳轉(zhuǎn)方向,使其跳到另一個路由3.next(false)? 返回原來的頁面4.next((vm)=>{})? 僅在beforeRouteEnter中可用疲吸,vm是組件實例座每。
router.afterEach
示例router.afterEach((to,from)=>{console.log('路由全局勾子:afterEach---沒有next方法')})
在所有路由跳轉(zhuǎn)結(jié)束的時候調(diào)用,和beforeEach是類似的摘悴,但是它沒有next方法
組件路由勾子
和全局勾子不同的是峭梳,它僅僅作用于某個組件,一般在.vue文件中去定義蹂喻。
beforeRouteEnter
示例? beforeRouteEnter (to,from, next) {console.log(this)//undefined葱椭,不能用this來獲取vue實例console.log('組件路由勾子:beforeRouteEnter')? ? next(vm=>{console.log(vm)//vm為vue的實例console.log('組件路由勾子beforeRouteEnter的next')? ? })? }
這個是一個很不同的勾子。因為beforeRouterEnter在組件創(chuàng)建之前調(diào)用口四,所以它無法直接用this來訪問組件實例孵运。
為了彌補這一點,vue-router開發(fā)人員蔓彩,給他的next方法加了特技治笨,可以傳一個回調(diào)驳概,回調(diào)的第一個參數(shù)即是組件實例。
一般我們可以利用這點旷赖,對實例上的數(shù)據(jù)進行修改顺又,調(diào)用實例上的方法。
我們可以在這個方法去請求數(shù)據(jù)等孵,在數(shù)據(jù)獲取到之后稚照,再調(diào)用next就能保證你進頁面的時候,數(shù)據(jù)已經(jīng)獲取到了俯萌。沒錯果录,這里next有阻塞的效果。你沒調(diào)用的話绳瘟,就會一直卡在那
tip:next(vm=>{console.log('next')? })這個里面的代碼是很晚執(zhí)行的雕憔,在組件mounted周期之后。沒錯糖声,這是一個坑斤彼。你要注意。beforeRouteEnter的代碼時很早執(zhí)行的蘸泻,在組件beforeCreate之前琉苇;但是next里面回調(diào)的執(zhí)行,很晚悦施,在mounted之后并扇,可以說是目前我找到的,離dom渲染最近的一個周期抡诞。
beforeRouteLeave
beforeRouteLeave (to, from,next) {? ? console.log(this)? ? //可以訪問vue實例? ? console.log('組件路由勾子:beforeRouteLeave')next()? },
在離開路由時調(diào)用穷蛹。可以用this來訪問組件實例昼汗。但是next中不能傳回調(diào)肴熏。
beforeRouteUpdate
這個方法是vue-router2.2版本加上的。因為原來的版本中顷窒,如果一個在兩個子路由之間跳轉(zhuǎn)蛙吏,是不觸發(fā)beforeRouteLeave的。這會導致某些重置操作鞋吉,沒地方觸發(fā)鸦做。在之前,我們都是用watch $route來hack的谓着。但是通過這個勾子泼诱,我們有了更好的方式。
老實講漆魔,我沒用過這個勾子坷檩,所以各位可以查看一下文章之前的文檔却音,去嘗試一下,再和我交流交流矢炼。
指令周期
綁定自定義指令的時候也會有對應的周期系瓢。
這幾個周期,我比較常用的句灌,一般是只有bind夷陋。
bind
只調(diào)用一次,指令第一次綁定到元素時調(diào)用胰锌,用這個鉤子函數(shù)可以定義一個在綁定時執(zhí)行一次的初始化動作骗绕。
inserted
被綁定元素插入父節(jié)點時調(diào)用(父節(jié)點存在即可調(diào)用,不必存在于 document 中)资昧。
實際上是插入vnode的時候調(diào)用酬土。
update
被綁定元素所在的模板更新時調(diào)用,而不論綁定值是否變化格带。通過比較更新前后的綁定值撤缴,可以忽略不必要的模板更新。
慎用叽唱,如果在指令里綁定事件屈呕,并且用這個周期的,記得把事件注銷
componentUpdated
被綁定元素所在模板完成一次更新周期時調(diào)用棺亭。
unbind
只調(diào)用一次虎眨, 指令與元素解綁時調(diào)用。
Vue.nextTick镶摘、vm.$nextTick
示例:? created () {this.$nextTick(()=>{console.log('nextTick')//回調(diào)里的函數(shù)一直到真實的dom渲染結(jié)束后嗽桩,才執(zhí)行? ? })console.log('組件:created')? },
nextTick方法的回調(diào)會在dom更新后再執(zhí)行,因此可以和一些dom操作搭配一起用凄敢,如 ref涤躲。
非常好用,可以解決很多疑難雜癥贡未。
場景:你用ref獲得一個輸入框,用v-model綁定蒙袍。在某個方法里改變綁定的值俊卤,在這個方法里用ref去獲取dom并取值,你會發(fā)現(xiàn)dom的值并沒有改變害幅。因為此時vue的方法消恍,還沒去觸發(fā)dom的改變。因此你可以把獲取dom值的操作放在vm.$nextTick的回調(diào)里以现,就可以了狠怨。