You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3 如何在所有子组件加载完成前正确显示Loader加载组件

问题根因

你的现有写法存在两个核心逻辑错误:

  1. 你用v-else控制<some-page>的渲染,初始状态下<some-page>没有被加入渲染树,它的异步加载逻辑根本不会启动,你直接在根组件的mounted钩子中修改componentsReady为true,等于Loader还没来得及完成渲染就被直接替换为<some-page>,自然看不到加载效果。
  2. 根组件的mounted触发时机和异步组件<some-page>的加载完成、内部子组件挂载完成的时机完全没有关联,不等组件加载完成就提前切换了状态。

调整方案

步骤1:修改模板逻辑

不要用v-else隐藏<some-page>,改用v-show保证它的异步加载逻辑可以提前启动,同时绑定事件监听加载状态:

<div id="app">
    <loader v-if="!componentsReady"></loader>
    <some-page v-show="componentsReady" @fully-mounted="componentsReady = true"></some-page>
</div>

步骤2:修改根组件逻辑

删除根组件mounted中提前修改componentsReady的代码:

import Loader from "./Loader";

const app = createApp({
    data() {
        return {
            componentsReady: false
        }
    },
    components: {
        SomePage: defineAsyncComponent(() => import('./somePage')),
        Loader
    }
});

app.mount('#app');

步骤3:修改SomePage组件逻辑

在SomePage确认自身所有子组件全部挂载完成后,向父组件抛出fully-mounted事件:

// SomePage.vue内部代码
export default {
    // 若存在内部异步子组件,请等待所有异步子组件加载完成后再抛出事件
    async mounted() {
        // 示例:如果有内部异步组件,可以等待所有加载Promise完成后再执行下面的emit
        // await Promise.all([异步子组件的加载Promise])
        this.$emit('fully-mounted')
    }
}

如果不需要等待SomePage内部的异步子组件加载完成,只需要等SomePage本身异步加载完成,也可以直接使用Vue异步组件内置的@load事件,不需要修改SomePage代码:

<div id="app">
    <loader v-if="!componentsReady"></loader>
    <some-page v-show="componentsReady" @load="componentsReady = true"></some-page>
</div>

内容的提问来源于stack exchange,提问作者Marko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 22:06:05