Vue各生命週期及相關功能觸發的研究
嘮叨一句
用了很長時間Vue了,但是對於它的各種生命週期及鉤子時而清除,時而糊塗,時常會掉進這些鉤子的坑裡不能自拔,今天干脆研究一下他們的順序,給自己和與我有相同經歷的同學們解惑。這裡只用很簡短的示例,演示了一些執行順序,不涉及整個的Vue應用。這些順序很重要。
程式碼一套
先放上示例程式碼,有興趣的同學可以貼去自己檢視,加深印象,其實可以不用看程式碼,直接去後面看結論。
<script> let app = new Vue({ el:"#app", data:{ test: 0, filter : 1, compute:2, flag: false }, created(){ console.log("同步的created開始 ") this.test++; //不會啟用updated,filters,watch,但是會改變資料,說明此時可觀測資料,且僅做資料前期處理。 //模擬非同步 setTimeout(()=>{ console.log("非同步的created開始 ") this.test++; //會啟用updated,filters,watch },100) }, mounted(){ console.log("mounted開始 ") this.test++; //會啟用updated,filters,watch,隨後所有的操作都按如下順序啟用:操作方法->watch,filters(computed如果有則在此之後),beforeUpdate,updated }, updated(){ console.log("updated開始") }, watch:{ test:{ handler(){ console.log("watch變數: test"); if (this.test >= 10) { this.flag = true; this.filter = 2; } }, /*immediate: true,*/ //如果false,則第一次watch在所監控的值第一次發生變化是發生,否則就是在beforeCreated之後發生。 }, flag:{ handler(){ console.log("watch變數: flag"); }, immediate: true, }, }, methods:{ add(){ this.test++; if (this.test > 5) { this.compute = 5; } if (this.test > 7) { this.filter = 5; } console.log("add方法執行"); } }, filters:{ filter1(data){ console.log("filters執行"); return data } }, computed:{ compute1(){ console.log("computed執行"); return this.compute } }, destroyed(){ console.log("destroyed執行"); }, beforeCreate(){ console.log("beforeCreate執行",this.test); this.test++; //這裡是找不到test的,說明此時是觀測不到資料的。 }, beforeDestroy(){ console.log("beforeDestroy執行"); }, beforeMount(){ this.test++; //資料會變化,但是不會啟用updated,filters,watch,隨後filters和computed會執行,然後是mounted, console.log("beforeMount執行",this.test); }, beforeUpdate(){ console.log("beforeUpdate執行"); }, }) </script>
結論最重要
通過上面的程式碼,其實可以得出Vue基本的運作順序:
1. 毋庸置疑的在new了以後,就是beforeCreate,此時,無法修改任何資料,因為現在還什麼都找不到,示例中控制檯列印的也是undefined,自然,此階段不會觸發任何其他操作;
2. 第二步,其實並不一定是created,如果watch選項中有屬性“immediate: true”的物件時,此時會執行具有該屬性物件的watch操作,之後才是同步的created,在created裡就可以進行一些資料的初始化,然而這裡會有不同!!!
3. created裡面如果是同步的資料操作,則只會改變當前的資料,不會觸發watch,filters,computed及updated;但是,如果有非同步的請求(示例中用定時器模擬),如ajax,那麼,這個非同步的資料
4. 第三步,就是beforeMount,同樣的,在這一步裡也可以進行資料操作,操作的副作用(同步和非同步不一樣)和created是一樣的!!!
5. 第四步,就是filters和computed開始執行,因為資料初始化和觀測已經完成,此時就會進行和資料相關的其他操作了,注意:如果watch沒有“immediate: true”,到目前為之,它是不會執行的;
6. 第五步,mounted,此時開始,進行任何的操作,都會觸發相應的功能操作,基本順序如下:函式方法結束>>watch>>filters>>(computed如果有)>>beforeUpdate>>updated
7. 最後就是beforeDestroy和destroyed,這兩步主要是解除安裝一些事件繫結等,消除記憶體佔用。
8. 補充說明,watch如果沒有“immediate: true”,那麼它會在其監視的資料第一次發生非初始化狀態的改變時開始觸發,即不再是初始值時,或者人為呼叫時觸發;
9. 還要再囉嗦一句,雖然每次資料操作都會啟用watch,但是隻有資料變化的,其對應內容才會執行,沒有變化的則不會執行;filters每次都會觸發,且無論資料是否有變化,所有的filters每一次都會被觸發且執行,因此使用時,要適當考慮記憶體效能問題;computed有快取,只有對應的值發生變化時,才會觸發重新計算,順序在fliters之後。
總結一下,
上述9項中,最重要的就是功能性操作的觸發順序以及created非同步操作,理解了這些,就能解決一些匪夷所思的問題,比如初始化時莫名其妙的觸發updated,watch的時機不對等等。
本示例僅作如上研究測試,是否會與實際業務中產生偏差尚未知曉,如有大神發現,歡迎指正!不勝感激!