Vue 生命周期鉤子完整指南

2021-12-20 前端新世界

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,重要的是不僅要知道要使用什麼生命周期鉤子,還要知道為什麼要使用它。

生命周期鉤子可以幫助解決很多問題,但關鍵是要選擇最適合當前用例的。

希望這能幫助大家更徹底地了解生命周期鉤子以及如何在項目中的實現它。

相關焦點

  • Vue 3 生命周期完整指南
    本文主要內容:Vue生命周期鉤子有哪些首先,來看一下 選項API 和 組合 API中 Vue 3生命周期鉤子的圖表。在深入細節之前,這能加深我們的理解。在選項API中使用 Vue 生命周期鉤子使用 選項API,生命周期鉤子是被暴露 Vue實例上的選項。我們不需要導入任何東西,只需要調用這個方法並為這個生命周期鉤子編寫代碼。
  • Vue框架之生命周期鉤子
    vue中三大常用屬性的小結、生命周期鉤子的了解,以及指令的初步接觸。指令有點多,只能留到明天繼續補全了。一、回顧與生命周期補充說明三大屬性,當然vue肯定不止這些,只不過時間有限,只學下最常見的。1回顧每次new一個Vue實例都需要關聯模板,Vue會基於此模板進行視圖渲染。
  • Vue.js系列:生命周期鉤子
    開發人員提供了一個Web開發人員可以在Vue.js應用程式的整個生命周期中使用的各種方法的討論。生命周期鉤子是在Vue對象生命周期的某個階段執行的已定義方法。從初始化開始到它被破壞時,對象都會遵循不同的生命階段。這是一個著名的圖表,表示掛鈎順序。讓我們將代碼添加到鉤子並查看它們如何被解僱的階段。<!
  • 深入 Vue 生命周期
    ,以及各個生命周期應該幹什麼事單組件的生命周期父子組件的生命周期兄弟組件的生命周期宏mixin的生命周期生命周期:Vue 實例從開始創建、初始化數據、編譯模板、掛載Dom→渲染、更新→渲染、卸載等一系列過程,我們稱這是 Vue 的生命周期,各個階段有相對應的事件鉤子1.
  • Vue2.0 - 生命周期詳解
    Vue實例有一個完整的生命周期,也就是說從開始創建、初始化數據、編譯模板、掛載DOM、渲染-更新-渲染、卸載等一系列過程,我們稱為Vue實例的生命周期
  • 不來看看這些 VUE 的生命周期鉤子函數?|原力計劃 - CSDN
    作者 | huangfuyk責編 | 王曉曼出品 | CSDN 博客VUE的生命周期鉤子函數:就是指在一個組件從創建到銷毀的過程自動執行的函數,包含組件的變化。可以分為:創建、掛載、更新、銷毀四個模塊。註:在組件的整個生命周期內,鉤子函數都是可被自動調用的,且生命周期函數的執行順序與書寫的順序無關。
  • Vue的基本使用
    $watch('a', function (newValue, oldValue) {  // 這個回調將在 `vm.a` 改變後調用})小結2.3實例生命周期鉤子vue實例創建會經過很多初始化過程,這些過程都有相應的函數叫做生命周期鉤子可以幫助我們在不同階段添加自己的代碼去實現某種效果。
  • Vue中directive自定義指令
    自定義指令的生命周期(鉤子函數)只會在初始化時候調用一次,用於當前指令第一次綁定到元素時候調用被綁定的元素插入到父親節點時候調用指令所在組件的Vnode數據更新的時候調用,但是有可能並不會發生改變,這個時候,可以通過使用鉤子參數更新前後的值來區分不必要的模版更新
  • 優美的v-for列表加載動畫:vue動畫鉤子實踐
    原文轉自 優美的v-for列表加載動畫:vue動畫鉤子實踐 https://juejin.im/post/6869195042599206919最近忙完工作,重新擼了一遍vue官方文檔,發現很少被我用到的vue動畫神器,JavaScript鉤子函數
  • vue 和 微信小程序的區別
    寫了vue項目和小程序,發現二者有許多相同之處,在此想總結一下二者的共同點和區別。Part1生命周期先貼兩張圖:vue生命周期小程序生命周期相比之下,小程序的鉤子函數要簡單得多。vue的鉤子函數在跳轉新頁面時,鉤子函數都會觸發,但是小程序的鉤子函數,頁面不同的跳轉方式,觸發的鉤子並不一樣。
  • 阿里媽媽又做了新工具,幫你把 Vue2 代碼改成 Vue3 的
    其實 Vue 團隊已經儘可能地減少了破壞性更新,還提供了一份細緻的遷移指南[1],條數不少,但定睛一看,大部分都是體力活,有些很簡單,比如異步組件要多包上一層:還有一些就改起來有點麻煩,比如自定義指令生命周期的更名,和傳入參數的一些細微變化:
  • 實戰技巧,Vue 原來還可以這樣寫
    在Vue組件中,可以用過$on,$once去監聽所有的生命周期鉤子函數,如監聽組件的updated鉤子函數可以寫成 this.$on('hook:updated', () => {})2. 外部監聽生命周期函數今天同事在公司群裡問,想在外部監聽組件的生命周期函數,有沒有辦法啊?
  • vue的$nextTick的使用+源碼分析
    開始前,我覺得我們需要先弄清楚vue的$nextTick是幹什麼用的,它的存在是為了解決什麼問題?大家也可以自問一下。nextTick英文翻譯過來「下一個記號或者標記」,我覺得這裡應該用狀態來描述更加合理一些。
  • Taro 正式發布 3.4 版本: 全面支持 Preact & Vue 3.2
    支持 Composition API 版本的小程序生命周期鉤子Composition APIs[2]Vue 3.2 正式推出了 script setup[3] 語法,過去 Taro 的 Options 式小程序生命周期鉤子難以配合 script setup 語法進行使用。
  • Vue 項目中哪些問題戳中你的痛點?你又是如何解決的?(更新中)
    如下圖所示:解決方法1:首先我在data函數裡面進行定義定時器名稱:然後這樣使用定時器:最後在beforeDestroy()生命周期內清除定時器:方案1有兩點不好的地方,引用尤大的話來說就是:它需要在這個組件實例中保存這個 timer,如果可以的話最好只有生命周期鉤子可以訪問到它。
  • Vue3.0--Vue Composition API使用體驗
    components: {}, props: {}, data () { return {} }, created(){}, mounted () {}, watch:{}, methods: {}}在Vue3.x中也是可以適配的,對應的相關生命周期方法也可正常執行
  • React生命周期的正解
    關注 入坑網際網路 ,回復「加群」加入我們一起學習,天天進步前言任何一個應用程式都會有自己的完整生命周期。只有了解生命周期才有可能寫出性能更好更健壯的應用程式。當然對比後端,前端對生命周期的定義理解使用場景還是有很大區別。
  • 記一次Spring boot 和Vue前後端分離的入門培訓
    基於 Vue cli 項目腳手架,網址:cli.vuejs.org/zh/guide/運行以下命令其一來創建一個新項目,有默認選默認即可 vue create vue-hello-world (命令行) vue ui (界面)在創建好項目以後,運行以下命令將能看到初次項目創建的界面 cd vue-hello-world
  • 一名 Vue 程式設計師總結的 React 基礎
    React 生命周期圖解[1]我已經把這張圖印在腦子裡面了,沒事就自己畫畫,中間發散一些自己的思考。u1s1,不知道 react 的生命周期命名為什麼要怎麼長~~~, 小程序,vue 的都比較短。畢竟使用的頻率還是很高的,Hooks 除外。