Vue生命周期


Vue實例有一個完整的生命周期,即開始創建---》初始化數據---》編譯模板---》掛載DOM---》渲染---》更新---》渲染---》銷毀等一系列過程,這一系列過程我們稱之為Vue實例的生命周期,鈎子就是在某個階段給你一個做某些處理的機會。

先上一張圖來只管的感受一下Vue的生命周期:

Vue生命周期主要以下幾個鈎子函數:

1、beforeCreate():

   我們在實例化Vue的時候(new Vue),會首先初始化事件和生命周期,然后會調用這個鈎子函數,這個鈎子函數我們一般不會使用它去做太多功能。

   這個時候,數據data和el還沒有掛載到Vue實例上,只是一個空殼,是無法訪問到數據data和真實的dom掛載元素el的。

2、created():

   在實例創建后,會掛載數據data和綁定事件。然后會調用created鈎子函數,所以此時,實例已經完成了基本配置。

   這里可以使用數據data,也可以修改數據data,且這里的修改數據是不會觸發updated鈎子函數的。

      一般可以在這里做數據初始化的操作,不過如果請求過多且全部都是同步請求的話,可能會導致界面出現短暫的空白阻塞,所以是否在這里初始化請求數據,看個人需求。

   但是dom還是沒有掛載到界面,所以$el依舊是不可見的。

  

3、beforeMount():

  實例基本配置完成后,會去判斷實例是否有掛載el對象,如果有的話,就繼續向下編譯,如果沒有的話,就停止編譯,即意味着停止了生命周期,直到我們在該實例上手動掛載el,即調用vm.$mount("#app")

   這個鈎子函數,我們基本上也是不會去使用它的。

   它的作用主要是用來檢查,Vue實例中有沒有自定義template參數選項,如果有的話,會將其作為模板template編譯成虛擬dom放到render函數中准備渲染;但是如果我們已經自定義了render函數,會使用我們定義的render函數的返回值渲染到界面;如果都沒有,就將掛載元素el的html作為模板template編譯。

  可以看到自定義render函數優先級 > 自定義template參數選項 >  掛載元素el的outer HTML

  此時,我們就可以理解,為啥要先去判斷是否有掛載el對象了,因為我們需要通過el找到對應的out template

  找到實例或組件對應的模板,編譯成虛擬dom放入到render函數中,准備渲染,然后會執行beforeMount鈎子函數,這個函數中,虛擬dom已經創建完成,即將渲染。這里我們還可以修改data且不觸發updated鈎子函數,這將是我們不觸發updated鈎子函數去修改data的最后一次機會了,后面所有的修改都將觸發updated鈎子函數。

<div id='app'>{{a}}</div>

new Vue({
    data(){
        return {
            a:100,
        }
    },
    template:"<h1>{{a}}</h1>", render(createElement){ return createElement("h2",{
            attrs:{
                id:"aaa"
            },
            style:{
                border:"1px solid red"
            },
            on:{
                click(){
                    alert(1)
                }
            }
        },'this is a render fn')
    },
    beforeMount(){
        // 這里會去檢查我們是否有自定義render(),有的話,會將render函數的返回值渲染到app中,如果沒有render函數,會去查找是否有自定義template,有的話將template值渲染到app中
    }
})

4、mounted():

  接下來render后,渲染出真實dom,然后執行mounted()鈎子函數。

  此時,組件已經出現在頁面中,數據,真實dom都已經處理好了,事件也已經掛載好了,可以操作真實dom對象了。

  這里修改數據data,會觸發updated鈎子,需要注意的是,vue中所有的數據渲染都是異步的,這里我們通過 this.$el.innerHTML 是拿不到更新后的內容的,需要通過vue.$nextTick 去獲取

<div id='app'>{{a}}</div>

new Vue({
    el:"#app",
    data(){
        return {
            a:"hello"
        }
    },
    mounted(){
        this.a = 100;
        console.log(this.$el.innerHTML);
        this.$nextTick(()=>{
       // 會在updated鈎子函數之后執行 console.log(
"nextTick->",this.$el.innerHTML) }) } });

5、beforeUpdate() 和 updated():

  當組件和實例中的數據發生變化后,會立即執行beforeUpdate鈎子,然后vue的虛擬dom機制會重新創建新的虛擬dom,與上一次的虛擬dom樹利用diff算法進行對比后,重新渲染組件。

  更新完成后,會執行updated鈎子,數據和組件都已經更新完成,這是可以操作更新后的dom

  注意:updated()鈎子函數中不能再修改數據,否則會造成死循環

7、beforeDestroy():

  當經過某種途徑調用$destroy()后(如組件銷毀,路由切換或者手動調用vm.$destroy()),在實例銷毀之前,會立即觸發beforeDestroy鈎子。

  此時實例還是完全可用的。

  一般在這里做一些清掃工作,如清除定時器,清除非指令綁定事件等等。

<div id="app">
    <self-comp></self-comp>
<div>

<template>
    <div id="selfComp">
        <button @click="destroy">銷毀</button>
        <h1>{{count}}</h1>
    </div>
</template>

Vue.component("selfComp",{
    template:"#selfComp",
    data(){
        return {
            count:1,
        }
    },
    timer:null,
    methods:{
        destroy(){
            this.$destroy();
        }
    },
    mounted(){
        this.$options.timer = setInterval(function(){
            this.count+=1;
        }.bind(this),1000);
    },
    beforeDestroy(){
        clearInterval(this.$options.timer);
    }
})

new Vue({}).$mount("#app")

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM