第十六節(jié):Vue生命周期與鉤子函數(shù)

前沿:
通過前面幾節(jié)的學習,我們已經(jīng)對vue有了初步的了解,vue可以幫我們干什么,而接下來就介紹vue的生命周期和它常用的鉤子函數(shù),那么我們就來看看對于vue的生命周期.

1. 理解生命周期的含義

生命周期:就是一個組件從實例化創(chuàng)建并添加到DOM開始 ,一直到組件被銷毀的整個過程 。

生命周期函數(shù)(鉤子函數(shù)): 就是在Vue生命周期的整個過程的不同階段被調(diào)用的函數(shù)

2. 生命周期圖

首先來一下官網(wǎng)的對于vue生命周期的圖解, 官網(wǎng)上目前有8個生命周期函數(shù),
還有兩個我們之后再看. 先看看基本的8個鉤子函數(shù)

image

3. 鉤子函數(shù)的理解

通過打斷點的方式,讓我們好好理解聲明周期的鉤子函數(shù), 你們也可以自己復(fù)制代碼進行測試好好理解Vue的鉤子函數(shù)

<script>
    new Vue({
        el: "#app",
        data:{},
        methods:{},

        // 1\. 在實例化之前被調(diào)用 
        beforCreate: function(){
            // 這個方法的時候data還沒有加載,所以此方法用不到
            // 一般不會再這里處理什么事情
            alert("組件實例化之前執(zhí)行的函數(shù)");
            debugger;
        },

        // 2\. 實例化初始之后,被添加到DOM元素之前觸發(fā)
        created: function(){
            // 可以在這里發(fā)送ajax,初始化操作
            alert("組件實例化完畢,但頁面還未顯示");
            debugger;
        },

        // 3\. 在元素(虛擬DOM)已經(jīng)準備好被添加到DOM,但是還沒有添加時觸發(fā)
        beforeMount: function(){
            // 要保證有el,或者vm.$mount() 否則這里不會執(zhí)行
            alert("組件掛載前,但頁面還未顯示,但是虛擬DOM已經(jīng)配置");
            debugger;
        },

        // 4\. 會在元素創(chuàng)建后觸發(fā)
        mounted: function(){
            //  如果有template屬性模板,會用模板替換外部的el,只要有此屬性,直接卸載外部el找中的內(nèi)
            // 這將沒有任何意義了
            //  template只能有一個更元素,不能是文本節(jié)點, 
            // 真實的dom渲染完了,可以操作dom了
            alert("組件掛載后,此方法執(zhí)行后,頁面顯示");
            debugger;
        },

        // 5\. 在數(shù)據(jù)更新將要對DOM做一些修改時觸發(fā)
        beforeUpdate: function(){
            //  當頁面依賴的數(shù)據(jù)發(fā)生變化時才執(zhí)行,一般用watch來替換,這個方法不好用
            // 頁面依賴的數(shù)據(jù)發(fā)生變化,數(shù)據(jù)已變化,頁面還沒有渲染
            alert("組件更新前,但頁面還未顯示,但是虛擬DOM已經(jīng)配置");
            debugger;
        },

        // 6\. 后在DOM的更新已經(jīng)完成后觸發(fā)
        updated: function(){
            // 重新渲染頁面后執(zhí)行, 可以操作DOM了
            alert("組件更新后,此方法執(zhí)行后,頁面顯示");
            debugger;
        },

         // 7\. 在組件即將被銷毀并且從DOM上移出時觸發(fā)
        beforeDestroy: function(){
            //沒什么意義,死了就什么都干不了了
            alert("組件銷毀前");
            debugger;
        }

        // 8\. 組件被銷毀后觸發(fā)
        destroyed: function(){
            alert("組件銷毀");
            debugger;
        }
    })
</script>

實踐是檢驗道理的唯一標準,
這里只能通過注釋來介紹一下vue的鉤子函數(shù)的意義。
想要詳細了解還需要你親自測試體會

生命周期鉤子的 this 上下文指向調(diào)用它的 Vue 實例。

通過這張生命周期圖,我們發(fā)現(xiàn)我們之前還有一些內(nèi)容沒有測試到, 諸如使用$mount綁定DOM元素, 實例化時自定義template模板等,那么接下來就好好測試一些,生命周期圖所講述的內(nèi)容

4. 綁定節(jié)點

我們之前學到一直是使用vue配置對象里的el來綁定DOM節(jié)點

生命周期圖告訴我們,如果我們沒有el屬性就會查找vue實例對象有沒有通過$mount方法來綁定DOM元素
其實就算你是用el綁定了DOM元素,在Vue源碼中也是會轉(zhuǎn)為$mount處理

<div id="app">

    <div v-html="msg"></div>
</div>
<div id="haha"></div>

<script>
    const vm = new Vue({
        el:"#app",
        data: {
           msg:"hello"
        },

    })
    vm.$mount("#haha")
</script>

同時我們還會發(fā)現(xiàn),如果el$mount都存在,綁定的元素有差異,那么以el為主,因為生命周期圖告訴我們只有當el屬性不存在的時候,才會查看$mount方法

5. template模板編譯

我們之前學習一直使用的都是沒有template模板的, 根據(jù)生命周期圖顯示,如果我們沒有template,模板,我們就會將el 屬性對應(yīng)的掛在點作為我們的模板

如果有template模板,我們就會用以后的模板替換之前的模板

<div id="app">
    {{ msg }}
</div>

<script>
    const vm = new Vue({
        el:"#app",
        template:"<div id='haha'>我是小當家</div>",
        data: {
           msg:"hello"
        },
    })
</script>

5.1 注意template模板里只能有一個根標簽

所以下面的寫法會報錯,是錯誤的寫法

const vm = new Vue({
    template:`
        <div id='haha'>
            我是小當家
        </div>
        <span></span>
    `,
    data: {
        msg:"hello"
    },
})

5.2 改變數(shù)據(jù)綁定的位置

如果有template 模板,我們動態(tài)綁定的數(shù)據(jù),就需要在模板中綁定

<div id="app">
    {{ msg }}
</div>

<script>
    const vm = new Vue({
        el:"#app",
        template:"<div id='haha'>我是小當家{{ msg }}</div>",
        data: {
           msg:"hello"
        },
    })
</script>

6. 關(guān)于mounted鉤子函數(shù)中獲取DOM元素的問題

6.1 正常在mounted鉤子函數(shù)里獲取DOM
<div id="app">
    <div v-html="msg"></div>
</div>

<script>
    const vm = new Vue({
        el:"#app",
        data: {
           msg:"<h2 id='box'>hello</h2>"
        },
        mounted(){
            console.log("mounted:");
            console.log(box);
        },
    })
</script>

我們會發(fā)現(xiàn)獲取DOM元素完全沒有問題,

6.2 更改DOM節(jié)點內(nèi)容

如果我們動態(tài)的修改了DOM節(jié)點,那么我們在獲取看看

<div id="app">

    <div v-html="msg"></div>
</div>
<script>

    const vm = new Vue({
        el:"#app",
        data: {
            msg:"<h2 id='box'>hello</h2>"
        },
        mounted(){
            // 動態(tài)修改DOM 節(jié)點
            this.msg = `<h2 id="box">你好</h2>`
            // 獲取DOM 節(jié)點
            console.log(box);

        },
    })
</script>

這是我們就會發(fā)現(xiàn)我們獲取的還是原先的DOM節(jié)點, 此時去獲取節(jié)點內(nèi)容就會有問題,
獲取的DOM節(jié)點并不是更改后最新的DOM節(jié)點

6.3 解決動態(tài)DOM 節(jié)點的問題

我們可以使用$nextTice來解決此類問題

在下次 DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后立即使用這個方法,獲取更新后的 DOM。

$nextTick(),是將回調(diào)函數(shù)延遲在下一次dom更新數(shù)據(jù)后調(diào)用,簡單的理解是:數(shù)據(jù)更新后,在dom重新渲染完畢,自動執(zhí)行該函數(shù),

通過$nextTick 方法來異步操作vue實例

示例:

<div id="app">

    <div v-html="msg"></div>
</div>
<script>

    const vm = new Vue({
        el:"#app",
        data: {
            msg:"<h2 id='box'>hello</h2>"
        },
        mounted(){
            // 動態(tài)修改DOM 節(jié)點
            this.msg = `<h2 id="box">你好</h2>`
            // 獲取DOM 節(jié)點
            console.log(box);

            // 通過$nextTick異步處理方法來獲取就會得到最新的值
            this.$nextTick(() => {
                console.log(box);
            })
        },
    })
</script>

上面的示例,我們打印了2次box ,box是DOM元素的id,可以用來獲取DOM元素, 但是此時兩次獲取的DOM元素展示的結(jié)果不一樣

image

第一次獲取box雖然數(shù)據(jù)已經(jīng)改變, 頁面也準備重新渲染新的DOM元素, 但是此時DOM還沒有更新完成,就獲取box,獲取的就是原來的DOM元素內(nèi)容, $nextTick方法會在DOM元素更新完成以后才會觸發(fā)回調(diào)函數(shù),在回調(diào)函數(shù)中獲取的box才是更改后最新的DOM元素

建議在組件學習后在回來看:
帶有子組件的示例:

<div id="app">
    <child ref="child"></child>
</div>

<template id="child">
    <div>
        <span v-for="a in arr">{{a}}</span>
    </div>
</template>

<script>
    var vm = new Vue({   // 根實例
        el: '#app',
        data: {
            radio: 'home'
        },
        mounted() {
            console.log(1);     // 在執(zhí)行父組件的mounted
            // console.log(this.$refs.child.$el.innerHTML);
            // 這里打印的是 1,2,3的數(shù)組

            // 這里可以選擇$nextTick方法,這個是在頁面渲染完畢后執(zhí)行
            this.$nextTick(() => {
                console.log(this.$refs.child.$el.innerHTML);  // 這個時候才4,5,6
            })
        },
        components: {
            child: {
                template: '#child',
                data() {
                    return { arr: [1, 2, 3] }
                },
                mounted() {
                    console.log(2);    // 先打印子組件的mounted
                    this.arr = [4, 5, 6]; // 說明這里mounted是異步的
                }
            }
        }
    });
</script>

顯示結(jié)果

image

通過實例發(fā)現(xiàn),是不是用$nextTick方法在組件數(shù)據(jù)更新以后獲取的DOM元素的內(nèi)容都不一樣

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容