从父子组件的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

相关文章
相关标签/搜索