Vue.js请注意,mounted不能保证所有子组件也都已被装载吗?

时间:2019-02-01 15:16:07

标签: javascript vuejs2 hook

有人可以从VUE文档https://vuejs.org/v2/api/#mounted中解释以下通知吗?

  

请注意,mountd不能保证所有子组件也都已安装。

我已经测试了安装子级和子级子级,但是它们总是在根/应用程序组件之前安装,因此可以安全地使用“ mount”子级,而无需$ nextTick来访问DOM。子级和子级组件可以从根/应用程序模板访问DOM元素,尽管它是在子级之后安装的。另一方面,root / app也可以访问子级模板中的DOM元素。考虑这个例子...

<div id="app">
  {{ message }}
  <child></child>
  <span id="root"></span>
</div>

<script type="text/javascript">
  var subchild = {
    template: `<div>SUBCHILD<span id="subchild"></span></div>`,
    mounted() {
      console.log("Mounted SUBCHILD", document.getElementById('root'));
    }
  };

  var child = {
    template: `<div>CHILD<span id="child"></span><subchild></subchild></div>`,
    components : { subchild },
    mounted() {
      console.log("Mounted CHILD", document.getElementById('root'));
    }
  };

  var app = new Vue({
    el: '#app',
    components : { child },
    data() {
      return { message: 'APP' };
    },
    mounted() {
      console.log("Mounted APP", document.getElementById('root'), document.getElementById('child'), document.getElementById('subchild'));
    }

  })
</script>

https://jsfiddle.net/ecobyxrn/

控制台输出...

  

安装的子对象[对象HTMLSpan ...] [对象HTMLSpan ...] [对象HTMLSpan ...]

     

安装的孩子[对象HTMLSpan ...] [对象HTMLSpan ...] [对象HTMLSpan ...]

     

安装的APP [对象HTMLSpan ...] [对象HTMLSpan ...] [对象HTMLSpan ...]

因此,就我而言,我不理解该VUE通知。有人可以证明用例是在随后的root / app下挂载了子级吗?我认为VUE文档非常差,不能很好地解释它。我还通过注释掉el: '#app' +添加setTimeout(function() { app.$mount('#app'); }, 2000);来尝试延迟root / app的安装,但是结果是相同的。

此外,看到此图片... VUE.js mounted hooks parent + child

图片来源:https://medium.com/@brockreece/vue-parent-and-child-lifecycle-hooks-5d6236bd561f

在源页面上,有评论的人警告图像作者有关提及的VUE通知,但未解释。似乎每个人都知道该通知,但没人解释。

1 个答案:

答案 0 :(得分:2)

正如@RandyCasburn所述,组件可以异步加载。可以给components对象的每个属性一个组件定义对象,或者一个Promise最终用一个组件定义对象解析。因此,在这些情况下,可能是在异步加载的子级完成加载之前调用了父组件的mounted挂钩。

作为对此的简单测试,您可以更改基本组件的component对象,以在延迟后加载child组件:

components: {
  child: () => new Promise((resolve) => {
    setTimeout(() => {
      resolve(child)
    }, 2000)
  }) 
}

启动后,您会看到mounted挂钩中对子组件的引用是null

Vue文档没有将其作为警告的情况的潜在原因似乎没有帮助。而且,除了使用异步组件之外,我无法想到另一种情况,即在父组件的mounted钩子被触发时,子组件不会被挂载。


以下是使用您的代码的完整示例:

Vue.config.productionTip = false

var subchild = {
  template: `<div>SUBCHILD<span id="subchild"></span></div>`,
  mounted() {
    console.log("Mounted SUBCHILD", document.getElementById('root'), document.getElementById('child'), document.getElementById('subchild'));
  }
};

var child = {
  template: `<div>CHILD<span id="child"></span><subchild></subchild></div>`,
  components : { subchild: () => new Promise((resolve) => {
    setTimeout(() => {
      resolve(subchild)
    }, 2000)
  }) },
  mounted() {
    console.log("Mounted CHILD", document.getElementById('root'), document.getElementById('child'), document.getElementById('subchild'));
  }
};

var app = new Vue({
  el: '#app',
  components : { child: () => new Promise((resolve) => {
    setTimeout(() => {
      resolve(child)
    }, 2000)
  }) },
  data() {
    return { message: 'APP' };
  },
  mounted() {
    console.log("Mounted APP", document.getElementById('root'), document.getElementById('child'), document.getElementById('subchild'));
  }

})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  {{ message }}
  <child ref="child"></child>
  <span id="root"></span>
</div>