Vue 2 和 Vue 3 中的生命周期鉤子,其工作方式非常相似。
如果我們在項目中使用Options API,那就不必更改Vue生命周期鉤子的任何代碼,因為Vue 3兼容Vue之前的版本。
不過,如果使用的是Composition API,那麼訪問這些鉤子的方式略有不同。
這篇文章旨在幫助大家了解如何在Options API和Composition API中使用生命周期鉤子,從而寫出更優的代碼。
一起來看看吧!
什麼是Vue生命周期鉤子首先,讓我們來看一下關於Options API和Composition API中Vue 3生命周期鉤子的圖文概述。
從本質上說,每個主要的Vue生命周期事件都被分成兩個鉤子,在事件之前和事件之後被調用。你可以在Vue app中應用四個主要事件(也就是有8個主要鉤子)。
在Options API中使用Vue生命周期鉤子使用Options API時,生命周期鉤子作為選項提供給Vue實例。我們不需要導入任何東西,只需調用該方法並為該生命周期鉤子編寫代碼即可。
例如,假設我們要訪問mount()和updated()生命周期鉤子。代碼如下:
<script>
export default {
mounted() {
console.log('mounted!')
},
updated() {
console.log('updated!')
}
}
</script>夠簡單了吧?
OK,現在讓我們到Composition API中使用Vue 3生命周期鉤子。
在Vue 3 Composition API中使用Vue生命周期鉤子在Composition API中,我們必須先將生命周期鉤子導入到項目中,然後才能使用它們。這是為了儘可能保持項目的輕量級。
import { onMounted } from 'vue'除了beforeCreate和created(它們被setup方法本身所替代),我們可以在setup方法中訪問9個Options API生命周期鉤子。
onBeforeUpdate:在響應性數據更新和重新渲染之前調用onBeforeUnmount:在銷毀Vue實例之前調用onActivated:在激活保持活動的組件時調用onDeactivated:當停用保持活動的組件時調用onErrorCaptured:從子組件捕獲錯誤時調用當我們導入這些鉤子並在代碼中訪問時,如下所示:
<script>
import { onMounted } from 'vue'
export default {
setup () {
onMounted(() => {
console.log('mounted in the composition api!')
})
}
}
</script>
更新Vue 2代碼為Vue 3生命周期鉤子這個便捷的Vue 2到Vue 3生命周期映射就來自於Vue 3 Composition API文檔,非常有用。
beforeCreate -> 使用setup()beforeMount -> onBeforeMountbeforeUpdate -> onBeforeUpdatebeforeDestroy -> onBeforeUnmounterrorCaptured -> onErrorCaptured深入了解生命周期鉤子我們現在知道了兩個重點:
如何在Options API和Composition API中使用生命周期鉤子接下來讓我們深入了解每個生命周期鉤子,看看是它們如何使用的,我們可以在每個鉤子中編寫什麼樣的代碼,以及它們在Options API和Composition API中的區別。
組件創建鉤子——VueJS生命周期的開始組件創建鉤子是在程序運行要做的第一件事。
beforeCreate()——Options API
由於組件創建鉤子能初始化所有響應性數據和事件,所以beforeCreate不能訪問任何組件的響應性數據和事件。
以下面的代碼塊為例:
export default {
data() {
return {
val: 'hello'
}
},
beforeCreate() {
console.log('Value of val is: ' + this.val)
}
}val的輸出值是undefined,因為數據尚未初始化。你也不能在這個方法中調用組件方法。
如果你想看可用內容的完整列表,建議只運行console.log(this)來查看已初始化的內容。當使用Options API時,這在所有其他鉤子中也有用。
當你需要某種不需要分配給數據的邏輯/API調用時,使用beforeCreate鉤子很有用。因為如果我們現在給數據分配一些東西,一旦狀態被初始化數據就會丟失。
created()——Options API
我們現在可以訪問組件的數據和事件。因此,修改上面的示例以便使用created代替beforeCreate,並查看輸出如何變化。
export default {
data() {
return {
val: 'hello'
}
},
created() {
console.log('Value of val is: ' + this.val)
}
}輸出為:Value of val is: hello,因為已經初始化了數據。
在處理讀取/寫入響應性數據時,使用created方法很有用。例如,如果你想進行API調用,然後存儲該值,就到了created方法大顯身手的時候了。
此處,created比mounted更好,是因為這是在Vue同步初始化過程的早期,並且你可以隨意執行數據讀/寫。
至於Composition API Creation鉤子怎麼樣?
對於使用Composition API的Vue 3生命周期鉤子,beforeCreate和created都被setup()方法替換。這意味著你本應放入這些方法中的任何代碼現在都位於setup方法中。
我們剛剛在創建生命周期鉤子中編寫的代碼得重寫:
import { ref } from 'vue'
export default {
setup() {
const val = ref('hello')
console.log('Value of val is: ' + val.value)
return {
val
}
}
}
掛載鉤子——訪問DOM這些掛載鉤子處理掛載和渲染組件,是項目和應用程式中最常用的一些鉤子。
beforeMount()和onBeforeMount()
在實際渲染和掛載組件DOM之前調用。在這一步中,根元素還不存在。在Options API中,可以通過this.$el訪問。在Composition API中,你必須在根元素上使用ref才能執行此操作。
export default {
beforeMount() {
console.log(this.$el)
}
}使用ref的Composition模板如下所示。
<template>
<div ref='root'>
Hello World
</div>
</template>然後,對應的腳本嘗試訪問ref。
import { ref, onBeforeMount } from 'vue'
export default {
setup() {
const root = ref(null)
onBeforeMount(() => {
console.log(root.value)
})
return {
root
}
},
beforeMount() {
console.log(this.$el)
}
}由於尚未創建app.$el,因此輸出將為undefined。
mount()和onMounted()
在第一次渲染組件後調用。此時元素可用於直接的DOM訪問。
在Options API中,我們可以使用this.$el來訪問DOM,而在Composition API中,我們需要使用refs來訪問Vue生命周期鉤子中的DOM。
import { ref, onMounted } from 'vue'
export default {
setup() { /* Composition API */
const root = ref(null)
onMounted(() => {
console.log(root.value)
})
return {
root
}
},
mounted() { /* Options API */
console.log(this.$el)
}
}
更新鉤子——VueJS生命周期中的響應性每當修改響應性數據時都會觸發updated生命周期事件,從而觸發渲染更新。
beforeUpdate()和onBeforeUpdate()
在數據更改時,且在重新渲染組件之前運行。這是在發生任何更改之前手動更新DOM的好地方。例如,你可以刪除事件偵聽器。
beforeUpdate可用於跟蹤對組件所做的編輯次數,甚至跟蹤創建undo功能的操作。
update()和onUpdate()
一旦DOM更新,就會調用updated方法。下面是一些同時使用beforeUpdate和updated的入門代碼。
<template>
<div>
<p>{{val}} | edited {{ count }} times</p>
<button @click='val = Math.random(0, 100)'>Click to Change</button>
</div>
</template>使用相應的腳本:
export default {
data() {
return {
val: 0
}
},
beforeUpdate() {
console.log("beforeUpdate() val: " + this.val)
},
updated() {
console.log("updated() val: " + this.val
}
}或者
import { ref, onBeforeUpdate, onUpdated } from 'vue'
export default {
setup () {
const count = ref(0)
const val = ref(0)
onBeforeUpdate(() => {
count.value++;
console.log("beforeUpdate");
})
onUpdated(() => {
console.log("updated() val: " + val.value)
})
return {
count, val
}
}
}這些方法很有用,但是我們可能要使用watcher來檢測數據變化以應對很多用例。watcher很不錯,因為可以給出被更新數據的舊值和新值。
另一種選擇是使用計算值來更改基於元素的狀態。
銷毀鉤子——清理組件的銷毀鉤子用於移除所有組件的過程。如果處理不當,刪除事件偵聽器和清理可能導致內存洩漏。
beforeUnmount()和onBeforeUnmounted()
這在組件開始銷毀之前調用,此時進行大部分(如果不是全部)清理工作。在這個階段,組件仍然是完全有功效的,也沒有破壞任何東西。
在Options API中刪除事件偵聽器的示例如下。
export default {
mounted() {
console.log('mount')
window.addEventListener('resize', this.someMethod);
},
beforeUnmount() {
console.log('unmount')
window.removeEventListener('resize', this.someMethod);
},
methods: {
someMethod() {
// do smth
}
}
}下面是在Composition API中的實現
import { onMounted, onBeforeUnmount } from 'vue'
export default {
setup () {
const someMethod = () => {
// do smth
}
onMounted(() => {
console.log('mount')
window.addEventListener('resize', someMethod);
})
onBeforeUnmount(() => {
console.log('unmount')
window.removeEventListener('resize', someMethod);
})
}
}你可以通過在Vite、vue-cli或任何支持熱重載的開發環境中工作來查看。當代碼更新時,某些組件將自行卸載和掛載。
unmounted()和onUnmounted()
此時,大部分組件及其屬性都已消失。所以現在我們來列印一些數據來查看到底還剩什麼,以及對項目是否有用。
import { onUnmounted } from 'vue'
export default {
setup () { /* Composition API */
onUnmounted(() => {
console.log('unmounted')
})
},
unmounted() { /* Options API */
console.log('unmounted')
}
}
激活鉤子——管理保持活動的組件保持活動標籤是動態組件的包裝元素。它存儲對非活動組件的緩存引用,以便Vue不必在每次動態組件改變時都要創建一個全新的實例。
對於這個特定的用例,Vue為我們提供了兩個生命周期鉤子
activate()和onActivated()
每當保持活動的動態組件重新激活時都會調用此方法——這意味著它現在是動態組件的活動視圖。
例如,如果我們使用保持活動的組件來管理不同的選項卡視圖,每次我們在選項卡之間切換時,當前選項卡都會運行這個激活鉤子。
假設我們使用保持活動的包裝器設置了以下動態組件。
<template>
<div>
<span @click='tabName = "Tab1"'>Tab 1 </span>
<span @click='tabName = "Tab2"'>Tab 2</span>
<keep-alive>
<component :is='tabName' class='tab-area'/>
</keep-alive>
</div>
</template>
<script>
import Tab1 from './Tab1.vue'
import Tab2 from './Tab2.vue'
import { ref } from 'vue'
export default {
components: {
Tab1,
Tab2
},
setup () { /* Composition API */
const tabName = ref('Tab1')
return {
tabName
}
}
}
</script>在Tab1.vue組件中,我們可以像這樣訪問激活鉤子。
<template>
<div>
<h2>Tab 1</h2>
<input type='text' placeholder='this content will persist!'/>
</div>
</template>
<script>
import { onActivated } from 'vue'
export default {
setup() {
onActivated(() => {
console.log('Tab 1 Activated')
})
}
}
</script>deactivated()和onDeactivated()
顧名思義,這在保持活動的組件不再是動態組件的活動視圖時調用。
此鉤子可用於在特定視圖失去焦點保存用戶數據和觸發動畫等用例。
我們可以像這樣捕獲鉤子。
import { onActivated, onDeactivated } from 'vue'
export default {
setup() {
onActivated(() => {
console.log('Tab 1 Activated')
})
onDeactivated(() => {
console.log('Tab 1 Deactivated')
})
}
}現在,當我們在選項卡之間切換時——將會緩存和保存每個動態組件的狀態。
Vue 3調試鉤子Vue 3為我們提供了兩個可用於調試的鉤子,分別是:
這兩個事件都採取了DebuggerEvent,允許我們判斷是什麼導致了Vue實例中的重新渲染。
export default {
onRenderTriggered(e) {
debugger
// inspect which dependency is causing the component to re-render
}
}
總結無論你決定使用Options API還是Composition API,重要的是不僅要知道要使用什麼生命周期鉤子,還要知道為什麼要使用它。
生命周期鉤子可以幫助解決很多問題,但關鍵是要選擇最適合當前用例的。
希望這能幫助大家更徹底地了解生命周期鉤子以及如何在項目中的實現它。