vue异步组件的隐患

138 阅读2分钟

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>

image.png

可以看到,其顺序是:父组件 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>

image.png

2、问题分析

至于为什么会产生上诉现象,就得从vue加载异步组件的机制开始说起。

以下是vue对异步组件的处理流程:

image.png

当我们使用同步的组件的时候,那非常愉快,组件会按正常流程初始化:

1、初始化父组件实例

2、挂载父组件

3、初始化子组件实例

4、挂载子组件

5、子组件挂载完毕,触发子组件 mounted 钩子

6、父组件挂载完毕,触发父组件 mounted 钩子

而当我们使用异步组件的时候,情况就会有所不同,其流程将为:

1、初始化父组件

2、挂载父组件

3、发现子组件是异步组件,加载子组件文件,并返回一个生成占位节点的组件构造函数

4、上述构造函数被调用,占位节点被生成

5、父组件挂载完毕,触发父组件 mounted 钩子

6、子组件文件加载完毕,触发强制刷新

7、重走同步组件的步骤,但父组件 mounted 不再被触发

3、ai的解释

chat.deepseek.com_a_chat_s_0928aadc-9872-40a0-9493-52fc38df8b0d.png