Vue3 如何在所有子组件加载完成前正确显示Loader加载组件
问题根因
你的现有写法存在两个核心逻辑错误:
- 你用
v-else控制<some-page>的渲染,初始状态下<some-page>没有被加入渲染树,它的异步加载逻辑根本不会启动,你直接在根组件的mounted钩子中修改componentsReady为true,等于Loader还没来得及完成渲染就被直接替换为<some-page>,自然看不到加载效果。 - 根组件的
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
相关产品推荐
相关产品推荐

