學習完 Vue 之後,想要透過單元測試守護你的專案,但又不知道從何起手?
別擔心,快來訂閱作者最新系列文 《小白也能輕鬆瞭解的 Vue3 單元測試!》
讓你的 Vue 專案更上一層樓!
生命週期(如上圖)主要是在說明一個元件從生(初始化)到死(註銷)的過程,對於生命週期有良好的理解,可以更有效的運用他,譬如要在哪個階段載入 AJAX 的資料?哪個階段之後才能開始撈 data
裡的資料?為了解決這一類時機的問題,Vue.js 提供了這些時機的呼叫方式,稱之為 hook。而為了要好好地瞭解 Vue.js 的生命週期,下面透過一個簡單的範例,來捕捉各種生命週期的狀態:
HTML部分
<div id="app">
{{ message }}
<div>
JavaScript部分
let vm = new Vue({
el:'#app',
data:{
message:'get Data!',
},
methods:{
handleOnClick: function(){
alert(this.message)
}
},
beforeCreate: function(){
alert('beforeCreate')
alert("el屬性: "+this.$el)
alert("data資料: "+this.$data.message)
},
created: function(){
alert('created')
alert("el屬性: "+this.$el)
alert("data資料: "+this.$data.message)
},
beforeMount: function(){
alert('beforeMount')
alert("el屬性: "+this.$el)
},
mounted: function(){
alert('mounted')
alert("el屬性: "+this.$el)
}
})
設定好一個 Vue.js 的實體之後,接著一步一步對照生命週期的圖來說明:
初始化 Vue.js 實體。
開始初始化 Vue.js 的生命週期。
在此週期下, $el
尚未被建立,且 data
此時也尚未被定義出來,說明在這個階段中我們可以做的基本上是在於資料尚未被讀取進來的事情。而深入查看 Vue.js 檔案 init.js
中,會發現此階段尚未初始化 props
、data
、methods
、watch
、computed
等 options
所以顯然上述的功能基本上是都不能夠使用的。
9/9前原文:開始注入依賴項目。
比較好理解的話應該是此階段會開始將父元件所提供的資料傳遞給子元件做接收。也就是說在 created
hook 執行前要將「提供/拿取 data
值」這件事情給初始化完畢,以供使用。
在官方文件 provide / inject 一文中提到,父元件可以透過 provide
傳遞一個物件或是讓函式回傳一個物件的方法,供給子元件利用 inject
來得到該物件。
程式碼的部分則可以透過 Vue.js 官方 github 庫的檔案 inject.js 中可以瞭解到底層的運作方式。
由 alert
取得 $el
結果為 undefined
, data
的結果為 get Data!
的結論得出:
在此週期下, $el
尚未被建立,但 data
此時已經可以讀取的到了,說明在這個階段中我們可以做的基本上在於讀取資料相關的事情。深入研究,查看 Vue.js 中裡的檔案 init.js
,會發現已經初始化props
、data
、methods
、watch
、computed
,因此也說明了若想要使用data
等等的資料的話,至少得等到created
這個階段才可以使用。
這個階段會檢查Vue實體中是否含有 $el
的項目,有的話就繼續檢查是否含有 template
,沒有的話則是等到手動調用 vm.$mount()
的時候才繼續。
這個階段會檢查 Vue.js 實體中是否含有 template
的項目,沒有的話會將被 $el
綁定的 outerHTML
區域作為樣板替換,若有的話則是將 template
編譯進 render function
。
由 alert
取得 $el
結果顯示此時已經抓的到 $el
:
在此週期下 DOM 已經被 Vue.js 載入了一個新的元素。但此時的差異在於, $el
裡面樣板語法尚未被賦予值進去,所以顯示的仍然是兩個花括號的部分{{ message }}
。
由 alert
取得 $el
結果顯示此時已經抓的到 $el
,並且此時樣板語法也確實的將資料傳遞進去,因此最後看到的是顯示get Data!
的字串而非 {{ message }}
了。而一般初始化的 Vue.js 元件的必經之路到此階段就結束了 (除了使用keep-alive
的元件,keep-alive
元件再次渲染時並不會觸發created
、mounted
等hooks),因此我們可以再次看向官網的說明圖中,此階段後的線條是虛線的部分。
此生命週期發生在資料即將被更新前,這個階段主要可以用在得知哪個元件即將發生資料改動,並且可以移除對其綁定的事件監聽器。
此階段已經重新渲染完成資料更新後的狀態,並且要注意在此期間更改狀態,如果要更改官方建議使用computed
或watch
來進行資料更改。
當一個實體要被銷毀前會觸發此生命週期(譬如透過主動調用vm.$destroy()
或是當該元素所綁定的v-if
條件為false
時)。而這個階段我們可以做一些提醒的動作,例如alert
來確認使用者的意圖。
當一個實體已經被銷毀時會觸發此生命週期,這個階段的銷毀意味著所綁定的watcher
、child components
以及event listeners
等等已經與原本元素毫無關聯了,但要注意的事情是父元件已經渲染在DOM上的視圖仍然會保留在頁面上,只有子元件會完全消失。
透過以上生命週期,大致上已經可以瞭解每個周期 Vue.js 正在做什麼事情、我們能做什麼事情了,而觸發渲染的關鍵時刻是beforeMount
到mounted
時以及beforeUpdate
至updated
的這兩個階段。
最後如果在編寫 Vue.js 時有遇到哪邊渲染有問題,或是資料讀取不到的時候,不彷查看一下是不是做了生命週期所不能及的事情喔!
黑黑:沒有我所不能及的事情!(翻滾)
init injection & reactivity
開始注入依賴項目。
請問「注入依賴項目」是什麼意思 XD
另外 typo: vm.#mount(el)
感謝 Kuro 大大指教,typo 已修正。
而 開始注入依賴項目。 的部分可能太大陸用語、太快帶過了,我順便將此回應修改至文章中:
比較好讓他人來理解的話應該是開始將父元件所提供的資料傳遞給子元件。也就是說在 created
hook 執行前要將「提供/拿取 data
值」這件事情給初始化完畢,以供使用。
在官方文件 provide / inject 一文中提到,父元件可以透過 provide
傳遞一個物件或是讓函式回傳一個物件的方法,供給子元件利用 inject
來得到該物件。
程式碼的部分則可以透過 Vue.js 官方 github 庫的檔案 inject.js 中可以瞭解到底層的運作方式。
有其他解說不清楚或有誤的地方還麻煩指教了
感謝分享
補充 new Vue() 是 Vue 2 的語法,
Vue 3 用 Vue.createApp() 取代 new Vue()
https://book.vue.tw/appendix/migration.html#%E5%85%83%E4%BB%B6%E5%AF%A6%E9%AB%94%E5%BB%BA%E7%AB%8B
Vue 2 support will end on Dec 31, 2023. Learn more about Vue 2 Extended LTS.
The Benefits of the New Vue 3 App Initialization Code