Vue.js注意mounted不保证所有子组件也都挂载了吗?

Vue.js Note that mounted does not guarantee that all child components have also been mounted?

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

Note that mounted does not guarantee that all child components have also been mounted.

我已经测试了安装子项和子项,但它们总是在 root/app 组件之前安装,因此在没有 $nextTick 访问 DOM 的情况下使用 "mounted" 是安全的。子组件和子组件可以访问 root/app 模板中的 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/

控制台输出...

Mounted SUBCHILD [object HTMLSpan...] [object HTMLSpan...] [object HTMLSpan...]

Mounted CHILD [object HTMLSpan...] [object HTMLSpan...] [object HTMLSpan...]

Mounted APP [object HTMLSpan...] [object HTMLSpan...] [object HTMLSpan...]

因此,就我而言,我不理解 VUE 通知。有人可以展示在 root/app 之后安装子项的用例吗?我觉得VUE doc很差,解释的不是很好。我还尝试通过注释掉 el: '#app' + 添加 setTimeout(function() { app.$mount('#app'); }, 2000); 来延迟安装 root/app 但结果是一样的。

另外看这张图...

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

在源页面,有人在评论中警告图像作者提到的 VUE 通知,但没有解释。那个通知好像大家都知道,但是没人解释。

如@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>