最近復習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()方法

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