1、结论
当Vue的子组件使用异步组件的时候,会使得父子组件间生命周期钩子的执行顺序发生改变,一些依赖于此的逻辑会出现问题。
当子组件是同步加载时, created 钩子与 mounted 钩子在父子组件间的执行顺序如下:
<template>
<div id="app">
<ChildComp></ChildComp>
</div>
</template>
<script>
import ChildComp from './components/ChildComp.vue';
export default {
name: 'App',
components: {
ChildComp,
// ChildComp: () => import('./components/ChildComp.vue'),
},
created() {
console.log('app created');
},
mounted() {
console.log('app mounted');
},
};
</script>
可以看到,其顺序是:父组件 created -> 子组件 created -> 子组件 mounted -> 父组件 mounted
而当我们使用异步的子组件时,其执行顺序就会变成:父组件 created -> 父组件 mounted -> 子组件 created -> 子组件 mounted
<template>
<div id="app">
<ChildComp></ChildComp>
</div>
</template>
<script>
// import ChildComp from './components/ChildComp.vue';
export default {
name: 'App',
components: {
// ChildComp,
ChildComp: () => import('./components/ChildComp.vue'),
},
created() {
console.log('app created');
},
mounted() {
console.log('app mounted');
},
};
</script>
2、问题分析
至于为什么会产生上诉现象,就得从vue加载异步组件的机制开始说起。
以下是vue对异步组件的处理流程:
当我们使用同步的组件的时候,那非常愉快,组件会按正常流程初始化:
1、初始化父组件实例
2、挂载父组件
3、初始化子组件实例
4、挂载子组件
5、子组件挂载完毕,触发子组件 mounted 钩子
6、父组件挂载完毕,触发父组件 mounted 钩子
而当我们使用异步组件的时候,情况就会有所不同,其流程将为:
1、初始化父组件
2、挂载父组件
3、发现子组件是异步组件,加载子组件文件,并返回一个生成占位节点的组件构造函数
4、上述构造函数被调用,占位节点被生成
5、父组件挂载完毕,触发父组件 mounted 钩子
6、子组件文件加载完毕,触发强制刷新
7、重走同步组件的步骤,但父组件 mounted 不再被触发