Vue 3 生命週期完整指南

做者:Michael Thiessen
譯者:前端小智
來源:news
點贊再看,微信搜索 大遷世界,B站關注 前端小智這個沒有大廠背景,但有着一股向上積極心態人。本文 GitHub https://github.com/qq44924588... 上已經收錄,文章的已分類,也整理了不少個人文檔,和教程資料。

最近開源了一個 Vue 組件,還不夠完善,歡迎你們來一塊兒完善它,也但願你們能給個 star 支持一下,謝謝各位了。html

github 地址:https://github.com/qq44924588...前端

image.png

Vue2 和 Vue3 中的生命週期鉤子的工做方式很是類似,咱們仍然能夠訪問相同的鉤子,也但願將它們能用於相同的場景。vue

若是項目使用 選項 API,就沒必要更改任何代碼了,由於 Vue3 兼容之前的版本。git

固然,咱們用 Vue3 就是要用它的 組合 API組合 API中訪問這些鉤子的方式略有不一樣,組合API在較大的Vue項目中特別有用。github

本文主要內容:面試

  1. Vue生命週期鉤子有哪些
  2. 選項API中使用 Vue 生命週期鉤子
  3. 組合API中使用Vue 3生命週期鉤子
  4. 將 Vue2 的生命週期鉤子代碼更新到 Vue3
  5. 看看Vue 2和Vue 3中的每一個生命週期鉤子vue-cli

    1. 建立
    2. 掛載
    3. 更新
    4. 卸載
    5. 激活
  6. Vue 3中的新調試鉤子

Vue生命週期鉤子有哪些

首先,來看一下 選項API 和 組合 API中 Vue 3生命週期鉤子的圖表。在深刻細節以前,這能加深咱們的理解。api

image.png

本質上,每一個主要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'

除了beforecatecreated(它們被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

若是咱們要在組件建立時訪問組件的數據和事件,能夠把上面的 beforeCreatecreated代替。

// 選項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()方法替換beforecatecreated。這意味着,在這些方法中放入的任何代碼如今都只在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')
    })
  }
}

如今,當咱們在選項卡之間切換時,每一個動態組件的狀態都將被緩存和保存。

image

Vue3 調試鉤子

Vue3 爲咱們提供了兩個可用於調試目的的鉤子。

  1. onRenderTracked
  2. onRenderTriggered

這兩個事件都帶有一個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/h...

交流

文章每週持續更新,能夠微信搜索「 大遷世界 」第一時間閱讀和催更(比博客早一到兩篇喲),本文 GitHub https://github.com/qq449245884/xiaozhi 已經收錄,整理了不少個人文檔,歡迎Star和完善,你們面試能夠參照考點複習,另外關注公衆號,後臺回覆福利,便可看到福利,你懂的。

相關文章
相關標籤/搜索