還有兩個特殊的(使用keep-alive):activated、deactivated(不詳述)
組件生命周期鈎子函數
還未掛載到DOM,不能訪問到$el屬性,$ref屬性內容為空數組
new Vue({
data () {
return {
a : 1
}
} ,
created (){
console.log( this.a ) // 1
}
})
這個生命周期階段比較常用,比如ajax請求獲取初始化數據對實例進行初始化預處理等操作;但要注意在結合vue-router使用時,進入created生命周期階段后是無法對掛載實例進行攔截的,此時實例已經創建完成;故如果需要某些數據獲取完成情況才允許進入頁面的場景,建議在路由鈎子beforeRouteEnter中實現。
beforeMount:
beforeMount之前,會找到對應的template,並編譯成render函數
(這個步驟如果使用.vue文件和運行時版本將會在構建時提前完成)
template查找的優先級順序:
template參數 > el 外部HTML
如果指定了render函數,則直接采用render函數,即忽略template參數和el外部HTML
寫個栗子測試:
<div id="app">template outside</div> ... import App from './App.vue'; // App是任一Vue組件對象 new Vue({ el: '#app', // template: '<p>template inside</p>', // part inside // render: h => h(App) // part render })
需要Vue完整版本支持,注釋part inside和part render依次打開即可觀察到三次不同的結果
Vue的編譯過程暫略
mounted
el被新創建的$el替換 ---- 怎么理解?
這個可以理解為掛載前為實例尋找了一個暫時容身之處el,編譯完成($el創建完成)后替換這個容身之處完成實例的掛載
如:之前那個栗子中,將part render打開后觀察生成的DOM結構,<div id="app">template outside</div>
這個節點即原el已經被替換掉
實例掛載到DOM上,此時可以通過DOM API獲取到DOM節點,$ref屬性可以訪問
雖然經常觀察到先進入子組件mounted,但根據Vue官方文檔:
注意 `mounted` 不會承諾所有的子組件也都一起被掛載。如果你希望等到整個視圖都渲染 完畢,可以用 [vm.$nextTick](https://cn.vuejs.org/v2/api/#vm-nextTick)
在這個階段改變data上的值,相關的computed屬性可以立刻更新;但需要進入到下一次DOM更新,才能看到DOM上數據更新
new Vue({
el: '#app', template: '<p id="testa">{{a}}</p>', router, data () { return { a : 0 } }, mounted() { this.a ++; console.log(this.b); // 2 console.log(document.getElementById('testa').innerHTML) // 0 }, computed :{ b (){ return this.a+1; } } })
beforeRouteEnter的next的勾子比mounted觸發還要靠后 - 這個待會說到路由相關鈎子時再展開
beforeUpdate
這里的更新對象是模板,即需要虛擬 DOM 重新渲染和打補丁,beforeUpdate發生在以上兩個流程之前,此時新的虛擬DOM已經生成
如果發生變更的數據在模板中並沒有使用(包括直接和間接,間接:比如某個依賴該數據的計算屬性在模板中使用了),則不會觸發更新流程!!!
如:
new Vue({ el: '#app', template: '<p id="testa">{{a}}</p>', router, data () { return { a : 0, b : 1 } }, mounted (){ this.b ++; // b並沒有在模板中使用 }, beforeUpdate (){ debugger; // 不會進入這個斷點 } })
在一些參考文章中看到:在這個鈎子函數中,可以對狀態進行進一步更改,不會再次觸發重渲染流程
--- 這個說法有問題
如果對狀態進行變更會導致重新進入beforeUpdate(這里變更的狀態同樣要在模板中使用,如果變更沒有在模板中使用的data,才不會再次觸發重渲染流程)
而且若變更操作不是基礎類型的簡單賦值,還會引起死循環(不斷重新進入beforeUpdate)!
看看這個栗子,依次把注釋打開測試
new Vue({ el: '#app', template: '<p id="testa">{{a}}</p>', router, data () { return { a : 0, c: 0 } }, beforeUpdate() { console.log(document.getElementById('testa').innerHTML) // this.c = 1; // this.c沒有在模板中使用,變更不會引起重渲染流程 // this.a = 3; // 會再次進入一次重渲染流程,第二次進入時發現a仍是3,值沒有變更,不會再次重渲染 // this.a ++; // 會引起死循環,每次進入重渲染流程時,a的值都會變更 }, updated() { console.log(document.getElementById('testa').innerHTML) } })
應該避免在這個鈎子函數中操作數據
beforeDestroy
實例銷毀之前調用。在這一步,實例仍然完全可用,this仍能獲取到實例
一般在這一步中進行:銷毀定時器、解綁全局事件、銷毀插件對象等操作
destroyed
Vue 實例銷毀后調用。調用后,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀
注意:vue2.0之后主動調用$destroy()不會移除dom節點,作者不推薦直接destroy這種做法,具體參考https://github.com/vuejs/vue/...,如果實在需要這樣用可以在這個生命周期鈎子中手動移除dom節點
總結
https://www.jianshu.com/p/7ff8f31afebe;
https://segmentfault.com/a/1190000013956945?utm_source=channel-newest;