Vue自定义事件通过父子组件通信协调骨架屏显隐:父组件用loading状态控制渲染,子组件在请求前派发start-loading、结束后派发end-loading事件实现精准加载控制。

Vue 自定义事件本身不直接实现骨架屏加载控制,但可以配合骨架屏组件、状态管理和生命周期,通过自定义事件来协调“显示/隐藏骨架屏”的时机。核心思路是:父组件控制骨架屏显隐状态,子组件(如请求数据的业务组件)通过自定义事件通知父组件“开始加载”或“加载完成”,从而驱动骨架屏切换。
用自定义事件触发骨架屏显隐
骨架屏通常是一个独立的 <skeleton></skeleton> 组件,用 v-if 或 v-show 控制是否渲染。父组件维护一个 loading 布尔状态,子组件在发起请求前派发 start-loading 事件,在请求结束(无论成功失败)后派发 end-loading 事件:
<!-- 父组件 -->
<template>
<div>
<Skeleton v-if="loading" />
<UserList v-else @start-loading="loading = true" @end-loading="loading = false" />
</div>
</template>
<p><script>
import Skeleton from './Skeleton.vue'
import UserList from './UserList.vue'</p><p>export default {
components: { Skeleton, UserList },
data() {
return { loading: false }
}
}
</script>
子组件内部正确派发事件
在 UserList.vue 中,不要在 mounted 直接调用 API(此时父组件可能还没监听事件),而应在 created 或显式方法中触发请求,并确保使用 this.$emit 派发事件:
创建 Flask + Vue.js 全栈项目,采用单端口架构、uv 依赖管理、结构化日志和生产级前端设计。当用户要求以下操作时触发:创建新的 Flask+Vue 项目、搭建 Web 应用、构建全栈 Python+Vue 应用、初始化 Flask Web 项目、设置单端口 Flask 前后端项目。触发词:新建项目、创建项目、搭建项目、Flask项目、Vue项目。
- 在请求前
this.$emit('start-loading') - 在
finally块中this.$emit('end-loading'),保证无论成功失败都关闭骨架屏 - 避免在
async/await外部或错误回调里遗漏end-loading
进阶:支持加载状态透传与防抖
若多个子组件共用同一骨架屏,可统一用事件总线或 provide/inject 传递加载控制权;也可封装一个 useLoading 组合式函数(Vue 3)或 mixin(Vue 2),自动绑定 start/end-loading 并处理重复请求防抖:
立即学习“前端免费学习笔记(深入)”;
- 例如:连续快速切换 tab 时,只响应最后一次请求的 loading 状态
- 可在派发
start-loading前加个防抖标识,或由父组件根据事件时间戳判断是否忽略旧事件 - 骨架屏组件自身也可监听全局 loading 事件(如用
$on),但推荐显式 props + 事件更可控
注意 Vue 版本差异
Vue 2 中用 $emit('event-name', payload);Vue 3 Composition API 中需用 defineEmits 声明并调用:
// UserList.vue (Vue 3)
<script setup>
const emit = defineEmits(['start-loading', 'end-loading'])
<p>const fetchUsers = async () => {
emit('start-loading')
try {
// 请求逻辑
} finally {
emit('end-loading')
}
}
</script>

















