Vue.js请注意,mount不保证所有子组件也已安装?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue.js请注意,mount不保证所有子组件也已安装?相关的知识,希望对你有一定的参考价值。

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

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

我已经测试了挂载子节点和子节点,但它们总是在root / app组件之前安装,所以使用“mount”安全无需$ nextTick来访问DOM。子项和子项组件可以从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/

控制台输出......

已安装的SUBCHILD [对象htmlSpan ...] [对象HTMLSpan ...] [对象HTMLSpan ...]

已安装的CHILD [对象HTMLSpan ...] [对象HTMLSpan ...] [对象HTMLSpan ...]

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

所以在我的情况下,我不明白VUE的注意事项。有人可以显示以后安装子项的用例,然后是root / app吗?我认为VUE doc非常差,并没有很好地解释它。我也尝试通过注释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通知但不解释它。似乎每个人都知道这个通知,但没有人解释它。

答案

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

以上是关于Vue.js请注意,mount不保证所有子组件也已安装?的主要内容,如果未能解决你的问题,请参考以下文章

将变量传递给 Vue.js 中的子组件

Vue中父组件和子组件生命周期是如何执行的?

vue.js 不会在mounted() 挂钩上更新

mount() 仅在组件 Vue.js 上运行一次

如何知道 vue.js 中何时加载了所有子组件

Vue.js相关问题一有关methodsmounted使用方法的整理