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

Vue如何复用加载Spinner模板及对应逻辑以避免重复编码

当然可以实现,以下是几种常用的复用方案,按推荐优先级排序:

方案1:封装通用加载包装组件(最推荐,符合Vue组件复用最佳实践)

你可以直接把加载逻辑封装成一个带插槽的通用组件,不需要高阶组件这么复杂,所有页面直接引入套在内容外面即可。
首先编写通用组件 PageLoaderWrapper.vue:

<template>
    <template v-if="isLoading">
        <Spinner full size="medium" />
    </template>
    <template v-else>
        <!-- 插槽承载各页面自定义内容 -->
        <slot />
    </template>
</template>

<script>
export default {
    computed: {
        isLoading() {
            return this.$store.getters['loader/isLoading'];
        },
    }
}
</script>

在任意页面引用使用即可:

<template>
    <PageLoaderWrapper>
        <p>Page data</p>
        <!-- 直接编写当前页面的所有内容即可 -->
    </PageLoaderWrapper>
</template>

<script>
import PageLoaderWrapper from '@/components/PageLoaderWrapper.vue'
export default {
    components: { PageLoaderWrapper }
    // 无需重复编写isLoading计算属性
}
</script>

该方案侵入性最低,加载逻辑完全收敛在封装组件内,后续需要调整加载样式、判断逻辑时只需要修改一次通用组件即可。

方案2:使用Mixin实现(适合不想修改页面template结构的场景)

如果你不想调整每个页面的template标签内容,也可以把计算属性抽成公共mixin:
首先编写 loader.mixin.js:

export default {
    computed: {
        isLoading() {
            return this.$store.getters['loader/isLoading'];
        },
    }
}

页面使用时直接引入mixin,保留原有template判断逻辑即可:

<template>
    <template v-if="isLoading">
        <Spinner full size="medium" />
    </template>
    <template v-else>
        <p>Page data</p>
    </template>
</template>

<script>
import loaderMixin from '@/mixins/loader.mixin.js'
export default {
    mixins: [loaderMixin]
    // 无需重复编写isLoading计算属性
}
</script>

注意:如果是Vue3项目更推荐用组合式函数代替mixin,可避免命名冲突、逻辑来源不清晰的问题

方案3:高阶组件实现(符合你最初的设想,Vue场景下使用频次较低)

高阶组件本质是接收一个组件作为参数,返回包装后的新组件,实现方式如下:
编写 withPageLoader.js:

import Spinner from '你的Spinner组件路径'
export default function withPageLoader(WrappedComponent) {
    return {
        computed: {
            isLoading() {
                return this.$store.getters['loader/isLoading'];
            }
        },
        render(h) {
            if (this.isLoading) {
                return h(Spinner, {
                    props: { full: true, size: 'medium' }
                })
            }
            return h(WrappedComponent, {
                attrs: this.$attrs,
                on: this.$listeners
            })
        }
    }
}

页面使用方式:

<template>
    <p>Page data</p>
</template>

<script>
import withPageLoader from '@/utils/withPageLoader'
export default withPageLoader({
    // 原页面的组件配置,无需编写任何加载相关逻辑
    name: 'YourPage',
    // 其他页面业务逻辑...
})
</script>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 09:54:03