刺猬猫阅读免费下载
126.01MB · 2025-10-14
在日常Vue3开发中,处理按钮的加载状态是一个非常常见的需求。当用户点击按钮触发异步操作(如API请求)时,我们需要:
本文将介绍一个优雅的通用解决方案,基于以下技术栈:
让我们先看一个常见的实现方式:
<template>
<div>
<el-button @click="handleClick" :loading="loading">获取数据</el-button>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
// 控制按钮loading状态
const loading = ref(false);
// 模拟异步请求
const fetchData = () => {
return new Promise<{ code: number; msg: string }>((resolve) => {
setTimeout(() => {
resolve({
code: 200,
msg: "请求成功",
});
}, 3000);
});
};
// 点击处理函数
const handleClick = async () => {
loading.value = true;
try {
await fetchData();
} finally {
loading.value = false;
}
};
</script>
这种实现方式存在以下几个问题:
我们可以通过封装一个通用的按钮组件来解决这些问题。这个组件将:
<template>
<el-button
v-bind="omit(attrs, 'onClick')"
@click="handleClick"
:loading="loading"
>
<slot></slot>
</el-button>
</template>
<script setup lang="ts">
import { useAttrs, ref } from "vue";
import { ElButton } from "element-plus";
import { omit } from "lodash-es";
// 禁用属性透传,避免事件重复触发
defineOptions({
inheritAttrs: false,
});
// 获取所有传入的属性和事件
const attrs = useAttrs();
// 内部维护loading状态
const loading = ref(false);
/**
* 处理按钮点击事件
* 1. 自动管理loading状态
* 2. 执行外部传入的异步回调
* 3. 确保finally中重置状态
*/
const handleClick = async () => {
loading.value = true;
try {
// 检查并执行外部传入的onClick回调
if (typeof attrs.onClick === "function") {
await attrs.onClick();
}
} finally {
// 确保在任何情况下都重置loading状态
loading.value = false;
}
};
</script>
属性透传控制
defineOptions({
inheritAttrs: false, // 禁用默认的属性透传
});
属性处理
v-bind="omit(attrs, 'onClick')" // 使用lodash-es的omit方法
异步处理
try {
await attrs.onClick?.();
} finally {
loading.value = false;
}
<template>
<div class="button-demo">
<!-- 基础用法 -->
<MyButton type="primary" @click="handleClick">
获取数据
</MyButton>
<!-- 带图标 -->
<MyButton type="success" @click="handleClick">
<template #icon>
<el-icon><Upload /></el-icon>
</template>
上传文件
</MyButton>
<!-- 不同尺寸 -->
<MyButton type="warning" size="small" @click="handleClick">
小型按钮
</MyButton>
</div>
</template>
<script setup lang="ts">
import MyButton from "./components/my-button.vue";
import { ElMessage } from "element-plus";
// 模拟异步请求
const fetchData = () => {
return new Promise<{ code: number; msg: string }>((resolve) => {
setTimeout(() => {
resolve({
code: 200,
msg: "操作成功",
});
}, 2000);
});
};
// 业务处理函数 - 只需关注业务逻辑
const handleClick = async () => {
const res = await fetchData();
ElMessage.success(res.msg);
};
</script>
<style scoped>
.button-demo {
display: flex;
gap: 16px;
}
</style>
简单易用
el-button
即可使用自动管理状态
类型安全
可扩展性
这个通用按钮组件解决方案具有以下优势:
希望这个解决方案能帮助你在 Vue3 项目中更优雅地处理按钮加载状态!