highlight: a11y-dark
theme: condensed-night-purple
作者:Michael Thiessen
譯者:前端小智
來源:news
點贊再看,微信搜索**【大遷世界】,B站關注【前端小智】**這個沒有大廠背景,但有著一股向上積極心態人,本文
GitHubhttps://github.com/qq449245884/xiaozhi 上已經收錄,文章的已分類,也整理了很多我的檔案,和教程資料,
最近開源了一個 Vue 組件,還不夠完善,歡迎大家來一起完善它,也希望大家能給個 star 支持一下,謝謝各位了,
github 地址:https://github.com/qq449245884/vue-okr-tree
Vue2 和 Vue3 中的生命周期鉤子的作業方式非常相似,我們仍然可以訪問相同的鉤子,也希望將它們能用于相同的場景,
如果專案使用 選項 API,就不必更改任何代碼了,因為 Vue3 兼容以前的版本,
當然,我們用 Vue3 就是要用它的 組合 API,組合 API中訪問這些鉤子的方式略有不同,組合API在較大的Vue專案中特別有用,
本文主要內容:
- Vue生命周期鉤子有哪些
- 在選項API中使用 Vue 生命周期鉤子
- 在組合API中使用Vue 3生命周期鉤子
- 將 Vue2 的生命周期鉤子代碼更新到 Vue3
- 看看Vue 2和Vue 3中的每個生命周期鉤子
- 創建
- 掛載
- 更新
- 卸載
- 激活
- Vue 3中的新除錯鉤子
Vue生命周期鉤子有哪些
首先,來看一下 選項API 和 組合 API中 Vue 3生命周期鉤子的圖表,在深入細節之前,這能加深我們的理解,

本質上,每個主要Vue生命周期事件被分成兩個鉤子,分別在事件之前和之后呼叫,Vue應用程式中有4個主要事件(8個主要鉤子),
- 創建 — 在組件創建時執行
- 掛載 — DOM 被掛載時執行
- 更新 — 當回應資料被修改時執行
- 銷毀 — 在元素被銷毀之前立即運行
在選項API中使用 Vue 生命周期鉤子
使用 選項API,生命周期鉤子是被暴露 Vue實體上的選項,我們不需要匯入任何東西,只需要呼叫這個方法并為這個生命周期鉤子撰寫代碼,
例如,假設我們想訪問mounted()和updated()生命周期鉤子,可以這么寫:
// 選項 API
<script>
export default {
mounted() {
console.log('mounted!')
},
updated() {
console.log('updated!')
}
}
</script>
在組合API中使用Vue 3生命周期鉤子
在組合API中,我們需要將生命周期鉤子匯入到專案中,才能使用,這有助于保持專案的輕量性,
// 組合 API
import { onMounted } from 'vue'
除了beforecate和created(它們被setup方法本身所取代),我們可以在setup方法中訪問的API生命周期鉤子有9個選項:
-
onBeforeMount– 在掛載開始之前被呼叫:相關的render函式首次被呼叫, -
onMounted– 組件掛載時呼叫 -
onBeforeUpdate– 資料更新時呼叫,發生在虛擬 DOM 打補丁之前,這里適合在更新之前訪問現有的 DOM,比如手動移除已添加的事件監聽器, -
onUpdated– 由于資料更改導致的虛擬 DOM 重新渲染和打補丁,在這之后會呼叫該鉤子, -
onBeforeUnmount – 在卸載組件實體之前呼叫,在這個階段,實體仍然是完全正常的,
-
onUnmounted– 卸載組件實體后呼叫,呼叫此鉤子時,組件實體的所有指令都被解除系結,所有事件偵聽器都被移除,所有子組件實體被卸載, -
onActivated– 被keep-alive快取的組件激活時呼叫, -
onDeactivated– 被keep-alive快取的組件停用時呼叫, -
onErrorCaptured– 當捕獲一個來自子孫組件的錯誤時被呼叫,此鉤子會收到三個引數:錯誤物件、發生錯誤的組件實體以及一個包含錯誤來源資訊的字串,此鉤子可以回傳false以阻止該錯誤繼續向上傳播,
使用事例:
// 組合 API
<script>
import { onMounted } from 'vue'
export default {
setup () {
onMounted(() => {
console.log('mounted in the composition api!')
})
}
}
</script>
將 Vue2 的生命周期鉤子代碼更新到 Vue3
這個從Vue2 到Vue3的生命周期映射是直接從Vue 3 Composition API檔案中獲得的:
-
beforeCreate-> 使用setup() -
created-> 使用setup() -
beforeMount->onBeforeMount -
mounted->onMounted -
beforeUpdate->onBeforeUpdate -
updated->onUpdated -
beforeDestroy->onBeforeUnmount -
destroyed->onUnmounted -
errorCaptured->onErrorCaptured
深入了解每個生命周期鉤子
我們現在了解了兩件重要的事情:
- 我們可以使用的不同的生命周期鉤子
- 如何在選項API和組合API中使用它們
我們深入一下每個生命周期鉤子,看看它們是如何被使用的,我們可以在每個鉤子中撰寫特定代碼,來測驗在Options API和Composition API中的各自的區別,
beforeCreate() – 選項 API
由于創建的掛鉤是用于初始化所有回應資料和事件的事物,因此beforeCreate無法訪問組件的任何回應資料和事件,
以下面的代碼塊為例:
// 選項 API
export default {
data() {
return {
val: 'hello'
}
},
beforeCreate() {
console.log('Value of val is: ' + this.val)
}
}
val的輸出值是 undefined,因為尚未初始化資料,我們也不能在這呼叫組件方法,
如果你想查看可用內容的完整串列,建議只運行console.log(this)來查看已初始化的內容,當使用選項API時,這做法在其他鉤子中也很有用,
created() – 選項 API
如果我們要在組件創建時訪問組件的資料和事件,可以把上面的 beforeCreate 用 created代替,
// 選項API
export default {
data() {
return {
val: 'hello'
}
},
created() {
console.log('Value of val is: ' + this.val)
}
}
其輸出為Value of val is: hello,因為我們已經初始化了資料,
在處理讀/寫反應資料時,使用created 的方法很有用, 例如,要進行API呼叫然后存盤該值,則可以在此處進行此操作,
最好在這里執行此操作,而不是在mounted 中執行此操作,因為它發生在Vue的同步初始化程序中,并且我們需要執行所有資料讀取/寫入操作,
那么組合API的創建鉤子呢?
對于使用 組合API 的 Vue3 生命周期鉤子,使用setup()方法替換beforecate和created,這意味著,在這些方法中放入的任何代碼現在都只在setup方法中,
// 組合AP
import { ref } from 'vue'
export default {
setup() {
const val = ref('hello')
console.log('Value of val is: ' + val.value)
return {
val
}
}
}
beforeMount() and onBeforeMount()
在組件DOM實際渲染安裝之前呼叫,在這一步中,根元素還不存在,在選項API中,可以使用this.$els來訪問,在組合API中,為了做到這一點,必須在根元素上使用ref,
// 選項 API
export default {
beforeMount() {
console.log(this.$el)
}
}
組合API中使用 ref:
// 組合 API
<template>
<div ref='root'>
Hello World
</div>
</template>
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,
mounted() and onMounted()
在組件的第一次渲染后呼叫,該元素現在可用,允許直接DOM訪問
同樣,在 選項API中,我們可以使用this.$el來訪問我們的DOM,在組合API中,我們需要使用refs來訪問Vue生命周期鉤子中的DOM,
import { ref, onMounted } from 'vue'
export default {
setup() { /* 組合 API */
const root = ref(null)
onMounted(() => {
console.log(root.value)
})
return {
root
}
},
mounted() { /* 選項 API */
console.log(this.$el)
}
}
beforeUpdate() and onBeforeUpdate()
資料更新時呼叫,發生在虛擬 DOM 打補丁之前,這里適合在更新之前訪問現有的 DOM,比如手動移除已添加的事件監聽器,
beforeUpdate對于跟蹤對組件的編輯次數,甚至跟蹤創建“撤消”功能的操作很有用,
updated() and onUpdated()
DOM更新后,updated的方法即會呼叫,
<template>
<div>
<p>{{val}} | edited {{ count }} times</p>
<button @click='val = Math.random(0, 100)'>Click to Change</button>
</div>
</template>
選項 API 方式:
export default {
data() {
return {
val: 0
}
},
beforeUpdate() {
console.log("beforeUpdate() val: " + this.val)
},
updated() {
console.log("updated() val: " + this.val
}
}
組合API的方式:
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
}
}
}
這些方法很有用,但是對于更多場景,我們需要使用的watch方法檢測這些資料更改, watch 之所以好用,是因為它給出了更改后的資料的舊值和新值,
另一種選擇是使用計算屬性來基于元素更改狀態,
beforeUnmount() 和 onBeforeUnmounted()
在卸載組件實體之前呼叫,在這個階段,實體仍然是完全正常的,
在 選項 API中,洗掉事件偵聽器的示例如下所示,
// 選項 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
}
}
}
// 組合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 () { /* 組合 API */
onUnmounted(() => {
console.log('unmounted')
})
},
unmounted() { /* 選項 API */
console.log('unmounted')
}
}
activated() and onActivated()
被keep-alive 快取的組件激活時呼叫,
例如,如果我們使用keep-alive組件來管理不同的選項卡視圖,每次在選項卡之間切換時,當前選項卡將運行這個 activated 鉤子,
假設我們使用keep-alive包裝器進行以下動態組件,
<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 () { /* 組合 API */
const tabName = ref('Tab1')
return {
tabName
}
}
}
</script>
在Tab1.vue組件內部,我們可以像這樣訪問activated鉤子,
<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()
被 keep-alive 快取的組件停用時呼叫,
這個鉤子在一些用例中很有用,比如當一個特定視圖失去焦點時保存用戶資料和觸發影片,
import { onActivated, onDeactivated } from 'vue'
export default {
setup() {
onActivated(() => {
console.log('Tab 1 Activated')
})
onDeactivated(() => {
console.log('Tab 1 Deactivated')
})
}
}
現在,當我們在選項卡之間切換時,每個動態組件的狀態都將被快取和保存,

Vue3 除錯鉤子
Vue3 為我們提供了兩個可用于除錯目的的鉤子,
onRenderTrackedonRenderTriggered
這兩個事件都帶有一個debugger event,此事件告訴你哪個操作跟蹤了組件以及該操作的目標物件和鍵,
onRenderTracked
跟蹤虛擬 DOM 重新渲染時呼叫,鉤子接收 debugger event 作為引數,此事件告訴你哪個操作跟蹤了組件以及該操作的目標物件和鍵,
<div id="app">
<button v-on:click="addToCart">Add to cart</button>
<p>Cart({{ cart }})</p>
</div>
const app = Vue.createApp({
data() {
return {
cart: 0
}
},
renderTracked({ key, target, type }) {
console.log({ key, target, type })
/* 當組件第一次渲染時,這將被記錄下來:
{
key: "cart",
target: {
cart: 0
},
type: "get"
}
*/
},
methods: {
addToCart() {
this.cart += 1
}
}
})
app.mount('#app')
renderTracked
當虛擬 DOM 重新渲染為 triggered.Similarly 為renderTracked,接收 debugger event 作為引數,此事件告訴你是什么操作觸發了重新渲染,以及該操作的目標物件和鍵,
用法:
<div id="app">
<button v-on:click="addToCart">Add to cart</button>
<p>Cart({{ cart }})</p>
</div>
const app = Vue.createApp({
data() {
return {
cart: 0
}
},
renderTriggered({ key, target, type }) {
console.log({ key, target, type })
},
methods: {
addToCart() {
this.cart += 1
/* 這將導致renderTriggered呼叫
{
key: "cart",
target: {
cart: 1
},
type: "set"
}
*/
}
}
})
app.mount('#app')
總結
無論你選擇使用選項API還是 組合API,不僅要知道要使用哪個生命周期掛鉤,而且要知道為什么要使用它,這一點很重要,
對于許多問題,可以使用多個生命周期鉤子,但是最好知道哪個是最適合你用例的,無論如何,你都應該好好考慮一下,并有充分的理由去選擇一個特定的生命周期鉤子,
我希望這能幫助大家更多地理解生命周期鉤子以及如何在大家的專案中實作它們,
~完,我是刷碗智,我要去刷碗了,骨的白,
代碼部署后可能存在的BUG沒法實時知道,事后為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug,
原文:https://learnvue.co/2020/12/how-to-use-lifecycle-hooks-in-vue3/
交流
文章每周持續更新,可以微信搜索「 大遷世界 」第一時間閱讀和催更(比博客早一到兩篇喲),本文 GitHub https://github.com/qq449245884/xiaozhi 已經收錄,整理了很多我的檔案,歡迎Star和完善,大家面試可以參照考點復習,另外關注公眾號,后臺回復福利,即可看到福利,你懂的,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/271237.html
標籤:AI
上一篇:圖靈獎今日出爐,“龍書” 作者、編程語言大佬 Alfred Aho 和 Jeffrey Ullman 獲獎
下一篇:2020 年前端技術發展盤點
