關於 Vue 的生命週期與鉤子函數

前言

一直以來,其實都有多多少少使用過 Vue,這個現在很火的 Web 框架,但是不知道為甚麼,總是覺得自己都在亂用,不知道自己在幹嘛。究其原因,其實還是因為學習的不夠扎實,太多東西都不求甚解,導致對於一些基本知識的掌握不到位,當然在實際的業務場景中就肯定會處處碰壁了。本篇來學習 Vue 的生命週期,真的非常重要,希望這次務必要好好的建立起這部分的知識。

正文

Vue 生命週期概述

每個 Vue 實例在創建時都是通過 Vue() 函數的,且經過一系列的初始化過程,設置數據監聽,將實例掛載到 DOM 上並更新(如有需要)等等。同時,這個初始化的過程中會運行一些叫做 生命週期鉤子 的函數,這非常重要且強大,因為這給了用戶在不同階段添加添加代碼的機會!

Vue 的生命週期如下圖:

鉤子對於 Vue 組件就好像把人的一生從出生到死亡分成好幾個階段,好比你一定是在出生時取名字,不會到死亡時才取名字,或是如果你想在出生時就交女朋友,那也是不可能的。

Vue 組件也一樣,每個階段都有各自該做的事情,所以用特定鉤子函數做特定時想做的事,比如 Ajax 數據獲取就可以在 mounted 階段做。接下來讓我們看看到底都有哪些鉤子函數:

vue 1.0+vue 2.0Description
initbeforeCreate組件實例剛被創建,組件屬性計算之前,例如 data 屬性
createdcreated組件實例創建完成,屬性已經被綁定,但是還沒被掛到 DOM 中(尚未有 $el 屬性)
beforeCompilebeforeMount模板掛載之前
compiledmounted模板掛載之後
beforeUpdate組件更新之前
updated組件更新之後
activated組件被激活時調用,for keep-alive
deactivated組件被移除時調用,for keep-alive
beforeDestroybeforeDestroy組件銷毀前調用
destroyeddestroyed組件銷毀後調用

整理是給已經學懂了的人看得,如果像我一樣還不是懂得很明白的人們,繼續接著下去分析每一個鉤子都做了些什麼。我們使用 Vue 框架,需要在合適的時間點做適當的事,完全了解 Vue 的生命週期,我們才能知道哪些事情該在哪個函數中做。

Vue 生命週期經歷的階段 + 鉤子函數

簡單來說,一個 Vue 實例的創建經歷很多個階段,而對於每個 Vue 組件又都根據我們的代碼而不盡相同,但是,大體來說,Vue 生命週期都會經歷以下階段:

  • 開始創建
  • 初始化數據
  • 編譯模板
  • 掛載 DOM
  • 渲染 <-> 更新
  • 銷毀

首先,一切的一切都是通過 new Vue() 創建一個 Vue 實例,接下來初始化事件和生命週期,這都是系統會幫我們做的,不在生命週期的範疇內,先不關心。接下來,就要進入第一個生命週期,beforeCreate

beforeCreate

在 Vue 實例初始化好後,這時其實所有的數據,包括 data 屬性, computed 屬性都還沒與實例真正綁定,也就是說此時根本還沒有值,也沒有真正的數據以及 DOM。通常我們可以在該鉤子添加 loading 的效果。

beforeCreate 之後,會做數據的生成,講白了也就是屬性的賦值,主要包括 data 屬性以及 computed 屬性運算。

created

這個時候,Vue 實例的屬性都有值了,但是 DOM 仍然還未生成,$el 屬性還不存在。簡單來說,就是這時候 data, computed 都做完了也都有值綁定好了,但是還沒有創建好 template 屬性對應的 html 元素,所以此時,就算更改數據,也不會觸發視圖的重新渲染。通常我們可以在這邊結束 loading 的效果,並提示用戶頁面完成之類的。

beforeMount

這個函數其實是在模板編譯(template)和數據掛載之前的鉤子。這個時候,this.$el 是有值的,但是數據還沒有掛載到頁面上,也就是說,此時頁面中的 {{...}} 還沒被替換為真實的值。

beforeMount 之後就是做模板編譯,也就是將所有數據替換模板中的內容({{...}})。模板編譯完後,就會進入到下一個生命週期。

mounted

這個時候,模板編譯完成,數據也都掛載完成,所以此時頁面上都可以顯示出正確的數據。一般來說,我們會在這個生命週期向後端發送異步請求(Ajax, axios 等等),獲取一些頁面渲染所需要的數據。

beforeUpdate

接下來的這個鉤子函數,是在組件更新前執行的,這也就意味著,首先要有數據更新,才會觸發該鉤子函數。而且,這邊要注意,更新的數據必須是模板上依賴的數據,否則不會,且也沒必要觸發組件更新。而所謂 beforeUpdate 則是指數據更新後,但對應的 DOM 中的 innerHTML 還未改變的時間段。

updated

該階段,組件中的數據(innerHTML)都相應的更新了,所以叫做 updated

activated/deactivated

這兩個鉤子看上面表格描述整理,實際上也不常用到,這邊先不做過多的探討。

beforeDestroy

顧名思義,就是在組件銷毀前觸發的鉤子函數。通常,我們可以在該鉤子函數向用戶發起 “確認刪除xxx?” 之類的提示。

destroyed

在組件銷毀後觸發的鉤子函數,通常用於回收數據,或是做一些清理工作等等。

測試 Vue 生命週期 代碼

<!DOCTYPE html>
<html>
<head>
    <title>Vue 生命週期測試</title>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
</head>
<body>
<div id="app">
     <p>{{ message }}</p>
</div>

<script type="text/javascript">
    
const app = new Vue({
    el: '#app',
    data: {
        message : "Vue 生命週期" 
    },
    beforeCreate: function() {
        console.group('beforeCreate 創建前狀態 ===============》')
        console.log("%c%s", "color:red" , "el     : " + this.$el) //undefined
        console.log("%c%s", "color:red","data   : " + this.$data) //undefined 
        console.log("%c%s", "color:red","message: " + this.message)  
    },
    created: function() {
        console.group('created 創建完畢狀態 ===============》')
        console.log("%c%s", "color:red","el     : " + this.$el) //undefined
        console.log("%c%s", "color:red","data   : " + this.$data) //已被初始化 
        console.log("%c%s", "color:red","message: " + this.message) //已被初始化
    },
    beforeMount: function() {
        console.group('beforeMount 掛載前狀態 ===============》')
        console.log("%c%s", "color:red","el     : " + (this.$el)) //已被初始化
        console.log(this.$el)
        console.log("%c%s", "color:red","data   : " + this.$data) //已被初始化  
        console.log("%c%s", "color:red","message: " + this.message) //已被初始化  
    },
    mounted: function() {
        console.group('mounted 掛載後狀態 ===============》')
        console.log("%c%s", "color:red","el     : " + this.$el) //已被初始化
        console.log(this.$el)
        console.log("%c%s", "color:red","data   : " + this.$data) //已被初始化
        console.log("%c%s", "color:red","message: " + this.message) //已被初始化 
    },
    beforeUpdate: function() {
        console.group('beforeUpdate 更新前狀態 ===============》')
        console.log("%c%s", "color:red","el     : " + this.$el)
        console.log(this.$el)
        console.log("%c%s", "color:red","data   : " + this.$data)
        console.log("%c%s", "color:red","message: " + this.message) 
    },
    updated: function() {
        console.group('updated 更新完成狀態 ===============》')
        console.log("%c%s", "color:red","el     : " + this.$el)
        console.log(this.$el)
        console.log("%c%s", "color:red","data   : " + this.$data)
        console.log("%c%s", "color:red","message: " + this.message)
    },
    beforeDestroy: function() {
        console.group('beforeDestroy 銷毀前狀態 ===============》')
        console.log("%c%s", "color:red","el     : " + this.$el)
        console.log(this.$el)
        console.log("%c%s", "color:red","data   : " + this.$data)
        console.log("%c%s", "color:red","message: " + this.message)
    },
    destroyed: function() {
        console.group('destroyed 銷毀完成狀態 ===============》')
        console.log("%c%s", "color:red","el     : " + this.$el)
        console.log(this.$el)
        console.log("%c%s", "color:red","data   : " + this.$data)
        console.log("%c%s", "color:red","message: " + this.message)
    }
})
</script>
</body>
</html>

打開控制台,我們可以看到打印結果:

注意 $el 的變化,確實在 created 階段還沒生成,但是 beforeMount 階段生成完畢。

data 的打印也表明,其實數據的創建在 created 階段
就已經完成了。

還有一個值得注意的地方,就是 {{message}} 在甚麼時候才被真正替換。在 beforeMount 階段,雖然 message 值已經生成(其實在 created 就生成好了),但是實際上還沒有替換掉 {{}} 中的值。等到 mounted 階段,才真正地將數據掛載到 DOM 上。

接下來,我們繼續測試,在控制台中輸入 app.message = '新的 Vue 生命週期'

可以看到,唯有模板依賴的數據發生變化,才會觸發 beforeUpdate 和 updated 鉤子函數,頁面當然也會重新渲染。

回顧 Vue 生命週期

最後在最一開始官方給的 Vue 生命週期的基礎上,添加一些總結與理解。

結語

理解 Vue 的生命週期對於使用上或是理解上都有很大的幫助,也可以更好的寫代碼以及操作頁面效果等等。都怪自己以前混水摸魚沒搞明白,現在才重學。希望看完這篇你有所收穫,若有錯誤,也歡迎前端大神們指證交流!

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Vue生命周期是指Vue实例从创建到销毁的整个过程,而钩子函数则是在不同的生命周期阶段执行的函数。Vue提供了一系列的钩子函数,用于在特定的生命周期阶段执行相应的操作。 以下是Vue生命周期钩子函数及其对应的生命周期阶段: 1. beforeCreate:在实例初始化之后,数据观测和事件配置之前被调用。 2. created:在实例创建完成后被立即调用。此时实例已完成以下配置:数据观测、属性和方法的运算、watch/event事件回调。然而,挂载阶段还没开始,$el属性目前不可见。 3. beforeMount:在挂载开始之前被调用。相关的render函数首次被调用。 4. mounted:el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子函数。此时,实例已完成以下配置:编译模板、把data里面的数据和模板生成html。注意此时还没有挂载到页面上。 5. beforeUpdate:数据更新时调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子函数中对更新之前的状态做一些操作。 6. updated:由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子函数。可以执行依赖于DOM的操作,但是要避免更改数据。 7. beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。 8. destroyed:实例销毁后调用。此时,所有的事件监听器被移除,所有的子实例也被销毁。 下面是一个简单的示例,演示了Vue生命周期钩子函数的使用: ```javascript new Vue({ el: '#app', data: { message: 'Hello Vue!' }, beforeCreate: function() { console.log('beforeCreate'); }, created: function() { console.log('created'); }, beforeMount: function() { console.log('beforeMount'); }, mounted: function() { console.log('mounted'); }, beforeUpdate: function() { console.log('beforeUpdate'); }, updated: function() { conso.log('updated'); }, beforeDestroy: function() { console.log('beforeDestroy'); }, destroyed: function() { console.log('destroyed'); } }); ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值