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

如何通过Vue的emit实现加载遮罩组件的显示与隐藏?

问题分析与修正方案

你的代码存在这几个核心问题:

  • 事件传递方向搞反:defineEmits是子组件用来向父组件发送事件的API,你在父组件里调用emit("showLoader"),本质是向父组件的上级组件发事件,根本传不到AppLoader子组件。
  • loading状态逻辑错误:子组件的showLoader是取反操作,但你需要的是直接通过true/false控制显示隐藏,不是切换状态。
  • 异步逻辑处理缺失:你在onMounted里同步调用"显示"和"隐藏",API请求是异步的,代码执行太快会导致loader根本来不及显示。
  • 模板与样式重复控制:同时用v-if和class控制显示,逻辑冗余。

修正后的代码

1. 重构AppLoader.vue(子组件)

子组件只负责接收父组件传递的loading状态,根据状态显示/隐藏加载层:

<script setup lang="ts">
import { defineProps } from 'vue';

// 定义props接收父组件的loading状态
const props = defineProps<{
  loading: boolean;
}>();
</script>

<template>
  <!-- 用props直接控制加载层显示,简化逻辑 -->
  <div v-if="props.loading" class="loader f-height f-width">
    LOADER WHOOOOOO
  </div>
  <slot></slot>
</template>

<style src="./app-loader.css" scoped lang="postcss" />

2. 简化app-loader.css

因为已经用v-if控制显示,去掉.loading类:

.loader {
  background: red;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 10;
  opacity: 0.5;
}

3. 修改使用组件的页面(父组件)

父组件维护loading状态,通过props传递给子组件,同时用异步逻辑处理API请求:

<template>
  <AppLoader :loading="isLoading">
    Some stuff that takes a while to load....
  </AppLoader>
</template>

<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import AppLoader from './AppLoader.vue';

const isLoading = ref(false);

onMounted(async () => {
  isLoading.value = true; // 开始请求时显示loader
  
  try {
    // 替换成你的实际API请求
    await fetch('https://your-api-url.com/data');
    // 处理返回的数据
  } catch (err) {
    // 处理请求错误
  } finally {
    isLoading.value = false; // 请求结束后隐藏loader
  }
});
</script>

逻辑说明

  • 父组件负责维护loading状态和处理异步请求,子组件只做UI展示,符合组件职责单一原则。
  • 用async/await确保loader在请求全周期内正确显示,避免同步代码导致的闪屏问题。
  • 父组件通过props传递状态是Vue中父控子的标准方式,emit则是子组件通知父组件(比如子组件内部触发的操作需要告知父组件),不要搞混两者的使用场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 22:21:00