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

最近複習vue的時候遇到了一個很奇怪的問題,咱們直接從實例中看: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>

整個過程是這樣的:node

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

然而結果是這樣的。app

因而開始的苦苦的探索之路。異步

咱們一塊兒來分析一下整個的執行過程:函數

  • 首先,頁面首次加載時,在子組件的mounted鉤子函數以前,已經把$el掛載到了頁面。
  • 而後執行子組件的mounted函數,將arr的值改變,致使頁面的從新渲染。
  • 再而後執行父組件的mounted函數,將子組件的innerHTML打印出來。

答案就在頁面的從新渲染這。執行完子組件的mounted函數後,會當即執行父組件的mounted函數。也就是說mounted之間的執行是同步執行的。可是咱們的頁面渲染是一個異步操做。也就是說在執行父組件的mounted方法時,頁面尚未渲染完成,因此致使了打印結果的不一致性。學習

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

在下次 DOM 更新循環結束以後執行延遲迴調。在修改數據以後當即使用這個方法,獲取更新後的 DOM。spa

因此,咱們對父組件的mounted作以下修改:code

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

 

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

相關文章
相關標籤/搜索