引言:
在前端开发中,按钮和弹窗是用户交互的重要组成部分。一个设计良好的按钮组件不仅能提升用户体验,还能减少重复代码,提高开发效率。今天,我将分享如何封装一个灵活且美观的确认按钮组件,支持多种颜色和自定义弹窗提示。
当然,作为一个程序员,我也深知写代码时的痛苦------比如当你写了一个完美的组件,结果测试告诉你:"这个按钮颜色太丑了,能不能换个粉色?"(内心 OS:粉色?你是认真的吗?)于是,我决定把这个组件设计得足够灵活,满足各种"奇怪"的需求。
1. 需求分析
在实际项目中,我们经常需要实现以下功能:
- 按钮样式多样化:支持不同颜色和尺寸。
- 弹窗提示:点击按钮后弹出确认弹窗,防止用户误操作。
- 事件处理:用户确认或取消后触发相应事件。
为了满足这些需求,我决定封装一个通用的 BtnConfirm
组件。毕竟,谁也不想每次写弹窗逻辑时都重复造轮子,对吧?(除非你真的喜欢加班。)
2. 组件设计
2.1 支持属性
- size :按钮尺寸,支持
sm
(小)、md
(中)、lg
(大)。 - color :按钮颜色,支持
blue
、green
、red
、purple
、orange
、teal
、pink
、gray
、yellow
。- (温馨提示:如果你选了
pink
,请确保你的用户不会觉得你在开玩笑。)
- (温馨提示:如果你选了
- confirmTitle:弹窗标题。
- confirmMessage:弹窗内容。
- confirmButtonText:确认按钮文本。
- cancelButtonText:取消按钮文本。
2.2 事件
- confirm:用户点击确认时触发。
- cancel:用户点击取消时触发。
3. 代码实现
以下是 BtnConfirm.vue
组件的完整代码:
html
<script setup>
import { ref } from 'vue';
const props = defineProps({
size: {
type: String,
default: 'md',
validator: (value) => ['sm', 'md', 'lg'].includes(value),
},
color: {
type: String,
default: 'blue',
validator: (value) =>
['blue', 'green', 'red', 'purple', 'orange', 'teal', 'pink', 'gray', 'yellow'].includes(value),
},
confirmTitle: {
type: String,
default: '确认操作',
},
confirmMessage: {
type: String,
default: '您确定要执行此操作吗?',
},
confirmButtonText: {
type: String,
default: '确定',
},
cancelButtonText: {
type: String,
default: '取消',
},
});
const showModal = ref(false);
const emit = defineEmits(['confirm', 'cancel']);
const getButtonStyle = () => ({
padding: props.size === 'sm' ? '5px 10px' : props.size === 'lg' ? '15px 30px' : '10px 20px',
fontSize: props.size === 'sm' ? '14px' : props.size === 'lg' ? '18px' : '16px',
});
const getColorStyle = () => {
const colors = {
blue: { button: 'linear-gradient(135deg, #409eff, #337ecc)' },
green: { button: 'linear-gradient(135deg, #67c23a, #4e9a2f)' },
red: { button: 'linear-gradient(135deg, #f56c6c, #c45656)' },
purple: { button: 'linear-gradient(135deg, #9c27b0, #7b1fa2)' },
orange: { button: 'linear-gradient(135deg, #e6a23c, #d48207)' },
teal: { button: 'linear-gradient(135deg, #20c997, #1aa179)' },
pink: { button: 'linear-gradient(135deg, #ff7eb9, #ff5c8d)' },
gray: { button: 'linear-gradient(135deg, #a0a0a0, #808080)' },
yellow: { button: 'linear-gradient(135deg, #ffc107, #e0a800)' },
};
return colors[props.color] || colors.blue;
};
const handleConfirm = () => {
emit('confirm');
showModal.value = false;
};
const handleCancel = () => {
emit('cancel');
showModal.value = false;
};
</script>
<template>
<div>
<button
class="btn-confirm"
:style="{ ...getButtonStyle(), background: getColorStyle().button }"
@click.stop="showModal = true"
>
<slot></slot>
</button>
<div v-if="showModal" class="modal-overlay" @click.self="handleCancel">
<div class="modal">
<h3>{{ confirmTitle }}</h3>
<p>{{ confirmMessage }}</p>
<div class="modal-actions">
<button class="modal-button cancel" @click="handleCancel">
{{ cancelButtonText }}
</button>
<button
class="modal-button confirm"
:style="{ background: getColorStyle().button }"
@click="handleConfirm"
>
{{ confirmButtonText }}
</button>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.btn-confirm {
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background 0.3s ease;
}
.btn-confirm:hover {
opacity: 0.9;
}
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal {
background: white;
border-radius: 10px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
width: 300px;
padding: 20px;
text-align: center;
animation: fadeIn 0.3s ease;
}
.modal h3 {
margin: 0 0 10px;
font-size: 18px;
color: #333;
}
.modal p {
margin: 0 0 20px;
color: #666;
}
.modal-actions {
display: flex;
justify-content: center;
gap: 10px;
}
.modal-button {
padding: 8px 16px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
transition: background 0.3s ease;
}
.modal-button.confirm {
color: white;
}
.modal-button.confirm:hover {
opacity: 0.9;
}
.modal-button.cancel {
background: #f0f0f0;
color: #333;
}
.modal-button.cancel:hover {
background: #e0e0e0;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
4. 使用示例
html
<template>
<BtnConfirm @confirm="handleConfirm" @cancel="handleCancel">
删除
</BtnConfirm>
</template>
<script setup>
import BtnConfirm from "@/zdpui/components/button/BtnConfirm.vue";
const handleConfirm = () => {
console.log('用户点击了确认');
};
const handleCancel = () => {
console.log('用户点击了取消');
};
</script>
5. 总结
通过封装 BtnConfirm
组件,我们实现了以下目标:
- 灵活性:支持多种颜色和尺寸,满足不同场景需求。
- 可维护性:代码结构清晰,易于扩展和维护。
- 用户体验:弹窗提示美观,交互友好。
当然,如果你觉得这个组件还不够完美,欢迎在评论区提出建议。毕竟,程序员的世界里,没有最好,只有更好!(除非你写的代码能自动修复 Bug,那请务必联系我!)
互动话题:
你在项目中是否遇到过类似的组件需求?你是如何解决的?欢迎分享你的经验!如果你喜欢这篇文章,别忘了点赞、转发、打赏!你的支持是我持续分享的动力!
求关注、求转发、求打赏!你们的支持是我最大的动力!