vue生命周期探究(一)
前言
在使用vue開發的過程中,我們經常會接觸到生命周期的問題。那么你知道,一個標準的工程項目中,會有多少個生命周期勾子嗎?讓我們來一起來盤點一下:
根組件實例: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個周期,是否看得頭昏眼花了呢?接下來讓我們一起來介紹一下各個周期的通常用途與使用細節吧
組件實例周期
這一塊vue2的官方文檔有一張圖示,我們簡要提一下用法和注意
beforeCreate
在實例初始化之后,數據觀測(data observer) 和 event/watcher 事件配置之前被調用。
tip:此時組件的選項還未掛載,因此無法訪問methods,data,computed上的方法或數據created
實例已經創建完成之后被調用。在這一步,實例已完成以下的配置:數據觀測(data observer),屬性和方法的運算, watch/event 事件回調。然而,掛載階段還沒開始,$el 屬性目前不可見。
這是一個常用的生命周期,因為你可以調用methods中的方法、改變data中的數據,并且修改可以通過vue的響應式綁定體現在頁面上、獲取computed中的計算屬性等等。
tip:通常我們可以在這里對實例進行預處理。 也有一些童鞋喜歡在這里發ajax請求,值得注意的是,這個周期中是沒有什么方法來對實例化過程進行攔截的。 因此假如有某些數據必須獲取才允許進入頁面的話,并不適合在這個頁面發請求。 建議在組件路由勾子beforeRouteEnter中來完成。beforeMonut
在掛載開始之前被調用:相關的 render 函數首次被調用。
mounted
el 被新創建的 vm.$el 替換,并掛載到實例上去之后調用該鉤子。如果 root 實例掛載了一個文檔內元素,當 mounted 被調用時 vm.$el 也在文檔內。
tip:1.在這個周期內,對data的改變可以生效。但是要進下一輪的dom更新,dom上的數據才會更新。 2.這個周期可以獲取 dom。 之前的論斷有誤,感謝@馮銀超 和 @AnHour的提醒 3.beforeRouteEnter的next的勾子比mounted觸發還要靠后 4.指令的生效在mounted周期之前beforeUpdate
數據更新時調用,發生在虛擬 DOM 重新渲染和打補丁之前。你可以在這個鉤子中進一步地更改狀態,這不會觸發附加的重渲染過程。
updated
由于數據更改導致的虛擬 DOM 重新渲染和打補丁,在這之后會調用該鉤子。當這個鉤子被調用時,組件 DOM 已經更新,所以你現在可以執行依賴于 DOM 的操作。然而在大多數情況下,你應該避免在此期間更改狀態,因為這可能會導致更新無限循環。
beforeDestroy
實例銷毀之前調用。在這一步,實例仍然完全可用。
tip:1.這一步還可以用this來獲取實例。 2.一般在這一步做一些重置的操作。比如清除掉組件中的 定時器 和 監聽的dom事件destroyed
Vue 實例銷毀后調用。調用后,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀。
全局路由鉤子
作用于所有路由切換,一般在main.js里面定義
router.beforeEach
示例 router.beforeEach((to, from, next) => {console.log('路由全局勾子:beforeEach -- 有next方法') next() })一般在這個勾子的回調中,對路由進行攔截。
比如,未登錄的用戶,直接進入了需要登錄才可見的頁面,那么可以用next(false)來攔截,使其跳回原頁面。
值得注意的是,如果沒有調用next方法,那么頁面將卡在那。
router.afterEach
示例 router.afterEach((to, from) => { console.log('路由全局勾子:afterEach在所有路由跳轉結束的時候調用,和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在組件創建之前調用,所以它無法直接用this來訪問組件實例。
為了彌補這一點,vue-router開發人員,給他的next方法加了特技,可以傳一個回調,回調的第一個參數即是組件實例。
一般我們可以利用這點,對實例上的數據進行修改,調用實例上的方法。
我們可以在這個方法去請求數據,在數據獲取到之后,再調用next就能保證你進頁面的時候,數據已經獲取到了。沒錯,這里next有阻塞的效果。你沒調用的話,就會一直卡在那
tip:next(vm=>{console.log('next') }) 這個里面的代碼是很晚執行的,在組件mounted周期之后。沒錯,這是一個坑。你要注意。 beforeRouteEnter的代碼時很早執行的,在組件beforeCreate之前; 但是next里面回調的執行,很晚,在mounted之后,可以說是目前我找到的,離dom渲染最近的一個周期。beforeRouteLeave
beforeRouteLeave (to, from, next) {console.log(this) //可以訪問vue實例console.log('組件路由勾子:beforeRouteLeave') next() },在離開路由時調用。可以用this來訪問組件實例。但是next中不能傳回調。
beforeRouteUpdate
這個方法是vue-router2.2版本加上的。因為原來的版本中,如果一個在兩個子路由之間跳轉,是不觸發beforeRouteLeave的。這會導致某些重置操作,沒地方觸發。在之前,我們都是用watch $route來hack的。但是通過這個勾子,我們有了更好的方式。
老實講,我沒用過這個勾子,所以各位可以查看一下文章之前的文檔,去嘗試一下,再和我交流交流。
指令周期
綁定自定義指令的時候也會有對應的周期。
這幾個周期,我比較常用的,一般是只有bind。
bind
只調用一次,指令第一次綁定到元素時調用,用這個鉤子函數可以定義一個在綁定時執行一次的初始化動作。
inserted
被綁定元素插入父節點時調用(父節點存在即可調用,不必存在于 document 中)。
實際上是插入vnode的時候調用。
update
被綁定元素所在的模板更新時調用,而不論綁定值是否變化。通過比較更新前后的綁定值,可以忽略不必要的模板更新。
慎用,如果在指令里綁定事件,并且用這個周期的,記得把事件注銷
componentUpdated
被綁定元素所在模板完成一次更新周期時調用。
unbind
只調用一次, 指令與元素解綁時調用。
Vue.nextTick、vm.$nextTick
示例:created () {this.$nextTick(() => {console.log('nextTick') //回調里的函數一直到真實的dom渲染結束后,才執行 }) console.log('組件:created') },nextTick方法的回調會在dom更新后再執行,因此可以和一些dom操作搭配一起用,如 ref。
非常好用,可以解決很多疑難雜癥。
轉載于:https://www.cnblogs.com/chris-oil/p/9241478.html
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的vue生命周期探究(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字符串文档的去重
- 下一篇: html5倒计时秒杀怎么做,vue 设