VUE生命周期
Vue實例從創建到銷毀的過程,就是生命周期。Vue中所有功能的實現都是圍繞其生命周期進行的,在生命周期的不同階段調用對應的鉤子函數實現組件數據管理與DOM渲染兩大重要功能。
一、Vue生命周期共可以分為八個階段,分別為:
1.beforeCreated(創建前)
2.created(創建後)
3.beforeMount(載入前)
4.mounted(載入後)
5.beforeUpdate(更新前)
6.updated(更新後)
7.beforeDestroy(銷毀前)
8.destroyed(銷毀後)
二、Vue生命周期的作用是什麼?
它的生命周期中有多個事件鉤子,讓我們在控制整個Vue實例的過程中,更容易形成良好的邏輯。
三、第一次頁面載入時,會觸發哪些鉤子?
第一次頁面載入時會觸發beforCreate、created、beforeMount與mounted這幾個鉤子。
四、簡述每個周期具體適合哪些場景
beforeCreate:可以在這裡載入loading事件,在載入實例時觸發。
created:初始化完成時的事件可以寫在這裡,比如這次此出處結束loading事件,非同步請求也適宜在這裡調用。
mounted:掛載元素,獲取到DOM節點
updated:如果對數據統一處理,在這裡可以寫上相應函數。
beforeDestroy:可以做一個確認停止事件的確認框。
五、created與mounted的區別
created:在模板渲染成html前調用,即通常初始化某個屬性值,然後再渲染成視圖。
mounted:在模板渲染成html後調用,通常是初始化頁面完成後,再對html的DOM節點,進行一些操作。
六、關於生命周期的詳細介紹
接下來,可以看下面程式碼來學習:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> <p>{{ message }}</p> <h1>{{message + '這是在outer HTML中的'}}</h1> </div> <script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script type="text/javascript"> const app = new Vue({ el: '#app', data: { message : "LJY learns more" }, template:"<h1>{{message +'這是在template模板中的'}}</h1>", // render: function(createElement) { // return createElement('h1', 'this is createElement') // }, beforeCreate: function () { console.group('beforeCreate 創建前狀態===============》'); console.log("%c%s", "color:red" , "el : " + this.$el); //undefined console.log("%c%s", "color:red","data : " + this.$data); //undefined console.log("%c%s", "color:red","message: " + this.message) }, created: function () { console.group('created 創建完畢狀態===============》'); console.log("%c%s", "color:red","el : " + this.$el); //undefined console.log("%c%s", "color:red","data : " + this.$data); //已被初始化 console.log("%c%s", "color:red","message: " + this.message); //已被初始化 }, beforeMount: function () { console.group('beforeMount 掛載前狀態===============》'); console.log("%c%s", "color:red","el : " + (this.$el)); //已被初始化 console.log(this.$el); console.log("%c%s", "color:red","data : " + this.$data); //已被初始化 console.log("%c%s", "color:red","message: " + this.message); //已被初始化 }, mounted: function () { console.group('mounted 掛載結束狀態===============》'); console.log("%c%s", "color:red","el : " + this.$el); //已被初始化 console.log(this.$el); console.log("%c%s", "color:red","data : " + this.$data); //已被初始化 console.log("%c%s", "color:red","message: " + this.message); //已被初始化 }, beforeUpdate: function () { console.group('beforeUpdate 更新前狀態===============》'); console.log("%c%s", "color:red","el : " + this.$el); console.log(this.$el); console.log("%c%s", "color:red","data : " + this.$data); console.log("%c%s", "color:red","message: " + this.message); }, updated: function () { console.group('updated 更新完成狀態===============》'); console.log("%c%s", "color:red","el : " + this.$el); console.log(this.$el); console.log("%c%s", "color:red","data : " + this.$data); console.log("%c%s", "color:red","message: " + this.message); }, beforeDestroy: function () { console.group('beforeDestroy 銷毀前狀態===============》'); console.log("%c%s", "color:red","el : " + this.$el); console.log(this.$el); console.log("%c%s", "color:red","data : " + this.$data); console.log("%c%s", "color:red","message: " + this.message); }, destroyed: function () { console.group('destroyed 銷毀完成狀態===============》'); console.log("%c%s", "color:red","el : " + this.$el); console.log(this.$el); console.log("%c%s", "color:red","data : " + this.$data); console.log("%c%s", "color:red","message: " + this.message) } }) </script> </body> </html>
參考上面的運行結果,我們可以發現
在beforeCreate中,el與data並未初始化。在created中完成了data的初始化,而el並沒有。在beforeMount中,完成了el與data的初始化,但是el還是{{message}},應用的虛擬Dom技術,先把這個地方給空住,到後面mounted掛載的時候,再把值渲染進去。而在mounted的時候,el與data已經完成載入。
當改變app.message的值時,將會觸發update的操作。
當對vue實例執行,app.$destroy()時:
再更新message時:
vue不再對動作進行響應了,但是原先而生成的dom元素還存在,可以理解為執行了destroy操作後,後續就不再受到vue的控制了。
關於mounted與beforeMount的區別:
判斷vue實例中,是否有el選項,有的話選擇繼續。如果沒有el的話,停止編譯直到在該vue實例上調用vm.$mounted(el),之後再繼續。之後,判斷vue實例中是否有template參數選項,有的話則將其作為模板編譯成render函數;若沒有template,就將外部HTML作為模板編譯。
具體的話,我們來看程式碼:
var app = new Vue({ el: '#app', data: { message : "LJY learns more" }, template:"<h1>{{message +'這是在template模板中的'}}</h1>", // render: function(createElement) { // return createElement('h1', 'this is createElement') // },
首先,會先去判斷是否有el選項,如果有即繼續,如果沒有的話就停止生命周期。隨後判斷是否有template選項,如若有的話,就執行。如果沒有template這一選項的話,就會執行outer HTML的。但如果把render函數的注釋解除掉的話,就會執行render函數。
因此,我們可以看到按優先順序來說 render function>template>outerHTML
在beforeMount的時候,$el還只是我們在HTML裡面寫的節點,然後到mounted的時候,它就把渲染出來的內容掛載到了DOM節點上。這中間的過程其實是執render function的內容;當執行完render function之後,就會調用mounted掛載完畢後,這個實例就算是走完流程。
後續的鉤子函數執行的過程都是需要外部的觸發才會執行,比如說有數據的變化,會調用beforeUpdate,然後經過Virtual DOM,最後upadated更新完畢。
beforeCreate:在實例初始化之後,data observer和event/watcher事件配置之前被調用,此時data、watcher、methods都沒有。這時,vue實例還是什麼都沒有,但是$route對象是存在的,可以根據路由資訊進行重定向之類的操作。
created:在實例已經創建完成之後被調用,在這一步,實例已經完成了data observer,屬性與方法的運算,watch/event事件回調。然而,掛載階段還沒開始,$el屬性目前不可見。此時,this.$data可以訪問,watcher、events、methods也出現了,若根據後台介面動態改變data與methods的話,是可行的。
beforeMount:在掛載開始之前被調用,相關的render函數首次被調用。但是render正在執行中,此時DOM還是無法操作的。頁面渲染時,所需要的數據應該盡量在這次之前完成賦值。
mounted:在掛載之後被調用,在這一步創建vm.$el並替換el,並掛載在實例上。此時元素已經渲染完成了,依賴於DOM的程式碼就放在此處,比如監聽DOM事件。
beforeUpdate:$vm.data更新之後,虛擬DOM重新渲染與打修補程式之前被調用,可以在這個鉤子中進一步地修改$vm.data,這不會觸發附加的重渲染過程。
updated:虛擬DOM重新渲染和打修補程式之後被調用。當這個鉤子被調用時,組件DOM的data已經更新,所以可以執行依賴於DOM的操作。但是不要在此時修改data,否則會繼續觸發beforeUpdate、updated這兩個生命周期,進入死循環。
beforeDestroy:實例被銷毀之前調用,在這一步,實例依然完全可用,實例要被銷毀了。
destroyed:Vue實例銷毀後調用,此時,Vue實例指示的所有東西已經解綁,所有的事件監聽器都已被移除,所有的子實例也已經被銷毀,此時只能加一些toast之類的東西。