有人可以从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的安装,但是结果是相同的。
图片来源:https://medium.com/@brockreece/vue-parent-and-child-lifecycle-hooks-5d6236bd561f
在源页面上,有评论的人警告图像作者有关提及的VUE通知,但未解释。似乎每个人都知道该通知,但没人解释。
答案 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>