Javascript Vue.js注意,mounted并不保证所有子组件都已安装?

Javascript Vue.js注意,mounted并不保证所有子组件都已安装?,javascript,vuejs2,hook,Javascript,Vuejs2,Hook,有人能解释一下VUE doc的以下通知吗 请注意,已安装并不保证所有子组件也已安装 我已经测试了挂载子项和子项,但它们总是在root/app组件之前挂载,所以使用“挂载”而不使用$nextTick访问DOM是安全的。子级和子级组件可以从根/应用程序模板访问DOM元素,尽管它是在子级之后装载的。另一方面,root/app还可以访问子模板中的DOM元素。考虑这个例子… <div id="app"> {{ message }} <child></child>

有人能解释一下VUE doc的以下通知吗

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

我已经测试了挂载子项和子项,但它们总是在root/app组件之前挂载,所以使用“挂载”而不使用$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>

{{message}}
var子子女={
模板:`SUBCHILD`,
安装的(){
log(“mountedsubchild”,document.getElementById('root');
}
};
变量子项={
模板:`CHILD`,
组件:{subchild},
安装的(){
log(“挂载的子对象”,document.getElementById(“根”);
}
};
var app=新的Vue({
el:“#应用程序”,
组件:{child},
数据(){
返回{message:'APP'};
},
安装的(){
console.log(“装入的应用程序”、document.getElementById('root')、document.getElementById('child')、document.getElementById('subchild');
}
})

控制台中的输出

已装入的子孩子[object HTMLSpan…][object HTMLSpan…][object HTMLSpan…]

已装入的子对象[object HTMLSpan…][object HTMLSpan…][object HTMLSpan…]

已装入的应用程序[对象HTMLSpan…][对象HTMLSpan…][对象HTMLSpan…]

因此,在我的情况下,我不理解VUE的通知。是否有人可以展示在root/app之后挂载子级的用例?我认为VUE doc很差,解释得不好。我还尝试通过注释掉
el:'#app'
+添加
setTimeout(function(){app.$mount('#app');},2000)来延迟安装root/app但结果是相同的

此外,请看这张图片。。。

图像来源:


在源页面,有人在评论中警告图片作者提到的VUE注意事项,但并没有解释。似乎每个人都知道这个通知,但没有人解释。

正如@RandyCasburn所提到的,组件可以异步加载。
components
对象的每个属性可以指定一个component definition对象,也可以指定一个最终与component definition对象解析的
Promise
。因此,在这些情况下,可能是在异步加载的子组件完成加载之前调用了父组件的
挂载的
钩子

作为一个简单的测试,您可以更改基本组件的
组件
对象,以便在延迟后加载
子组件

components: {
  child: () => new Promise((resolve) => {
    setTimeout(() => {
      resolve(child)
    }, 2000)
  }) 
}
您将看到
mounted
钩子中对子组件的引用在激发时为
null

Vue文档没有提到这是他们警告的场景的潜在原因,这似乎毫无帮助。而且,除了使用异步组件之外,我想不出另一种情况,即当启动父组件的
mounted
hook时,子组件不会被挂载


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

Vue.config.productionTip=false
var子子女={
模板:`SUBCHILD`,
安装的(){
console.log(“Mounted SUBCHILD”、document.getElementById('root')、document.getElementById('child')、document.getElementById('SUBCHILD');
}
};
变量子项={
模板:`CHILD`,
组件:{subchild:()=>新承诺((解析)=>{
设置超时(()=>{
解决(子儿童)
}, 2000)
}) },
安装的(){
console.log(“挂载的子项”、document.getElementById(“根”)、document.getElementById(“子项”)、document.getElementById(“子项”);
}
};
var app=新的Vue({
el:“#应用程序”,
组件:{child:()=>新承诺((解析)=>{
设置超时(()=>{
解决(儿童)
}, 2000)
}) },
数据(){
返回{message:'APP'};
},
安装的(){
console.log(“装入的应用程序”、document.getElementById('root')、document.getElementById('child')、document.getElementById('subchild');
}
})

{{message}}

您没有异步执行任何操作。将您的简单示例更改为使用异步组件或使用ES6导入加载组件,您可能会发现不同的情况。你的用例太基本了,无法加载延迟。你评论中的提琴现在会在应用程序之后加载子应用程序。演示文档的确切状态。(顺便说一句,我确实同意文档可以更清楚地说明这一点!)@thanksd在我的代码中,我订购了挂载子儿童、挂载儿童和挂载应用程序。您的订单与已安装的应用程序、已安装的子级、已安装的子级完全相反,并且也没有一些span元素可用@RandyCasburn我刚刚使用ES6导入/导出组件测试了我的样本,没有区别。只有在@thanksd的JSFIDLE中这样的异步组件中才有区别。所以,当SPA应用程序不使用异步组件(我处理的每个应用程序)时,我根本不需要在挂载的钩子中使用@nextTick回调?我认为VUE doc应该提到这一重要区别。@RandyCasburn,你是对的,我误读了日志输出。@mikep,没错,同步加载的组件从子孩子开始启动它们的
mounted
挂钩,因为每个组件都在等待子孩子加载后再加载。在我的示例中,异步加载的组件是从父级向下加载的,因为子级还没有解析,而
挂载的
钩子仍然会触发,因为它承诺它们将解析。但是,正如您所提到的,这些异步组件不能在父
挂载的
钩子中引用,这是Vue文档所描述的。顺便说一句@thanksd我已经将$nextTick()添加到您的小提琴中,“挂载的应用程序”仍然作为第一个被记录。现在我不理解VUE文档