從父子組件的mounted鈎子的同步執行與頁面的異步渲染看nextTick的用法


最近復習vue的時候遇到了一個很奇怪的問題,我們直接從實例中看:

<div id="app">
    <child ref="child"></child>
</div>
<template id="child">
    <ul>
        <li v-for='a in arr'>{{a}}</li>
    </ul>
</template>
<script src="../../node_modules/vue/dist/vue.js"></script>
<script>
    let child = {
        template:'#child',
        mounted(){this.arr = [4,5,6]},//改變arr的值
        data:function(){
            return {arr:[1,2,3]};
        },
    };
    
    let vm = new Vue({
        el:'#app',
        data:{
        },
        mounted(){
            console.log(this.$refs.child.$el.innerHTML);//獲取掛載到頁面中的child子組件的innerHTML
        },
        components:{
            child:child,
        },
    })
</script>

整個過程是這樣的:

  • 我在子組件的mounted函數中,改變了arr的值,這會重新觸發視圖的渲染。
  • 然后我緊接着在父組件的mounted函數中獲取子組件的innerHTML。

然而結果是這樣的。

於是開始的苦苦的探索之路。

我們一起來分析一下整個的執行過程:

  • 首先,頁面首次加載時,在子組件的mounted鈎子函數之前,已經把$el掛載到了頁面。
  • 然后執行子組件的mounted函數,將arr的值改變,導致頁面的重新渲染。
  • 再然后執行父組件的mounted函數,將子組件的innerHTML打印出來。

答案就在頁面的重新渲染這。執行完子組件的mounted函數后,會立即執行父組件的mounted函數。也就是說mounted之間的執行是同步執行的。但是我們的頁面渲染是一個異步操作。也就是說在執行父組件的mounted方法時,頁面還沒有渲染完成,所以導致了打印結果的不一致性。

所幸的是vue給我們提供了一個全局的API:nextTick函數,該函數的功能是:

在下次 DOM 更新循環結束之后執行延遲回調。在修改數據之后立即使用這個方法,獲取更新后的 DOM。

所以,我們對父組件的mounted做如下修改:

mounted(){
    this.$nextTick(() => console.log(this.$refs.child.$el.innerHTML))
    //console.log(this.$refs.child.$el.innerHTML)
},
//打印時異步渲染還未完成,所以打印的不是我們想要的結果.所以為保守起見,都為在執行mounted方法時添加一個this$nextTick()方法

 

大功告成,在實戰中學習,在問題中學習就是這么爽。


免責聲明!

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



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