vue3封装alert 提示组件 仿element-plus

这样的提示
我直接上代码了。组件如下
<template><div class="smart-alert" :class="alertClasses"><div class="alert-content"><div class="alert-icon"><slot name="icon"><component :is="typeIcon" /></slot></div><div class="alert-message"><div class="alert-title" v-if="title || $slots.title"><slot name="title">{{ title }}</slot></div><div class="alert-description"><slot>{{ message }}</slot></div></div></div><div class="alert-actions"><slot name="action"><el-button v-if="actionText" :type="actionType" link @click="handleAction">{{ actionText }}</el-button></slot><el-button v-if="closable" link class="alert-close" @click="handleClose"><el-icon><Close /></el-icon></el-button></div></div>
</template><script setup>
import { computed } from 'vue';
import { ElIcon, ElButton } from 'element-plus';
import { InfoFilled, SuccessFilled, WarningFilled, CircleCloseFilled, Close } from '@element-plus/icons-vue';const props = defineProps({// 提示类型type: {type: String,default: 'info',validator: (value) => ['info', 'success', 'warning', 'error'].includes(value),},// 标题title: {type: String,default: '',},// 消息内容message: {type: String,default: '',},// 操作按钮文字actionText: {type: String,default: '',},// 操作按钮类型actionType: {type: String,default: 'primary',},// 是否可关闭closable: {type: Boolean,default: false,},// 是否显示图标showIcon: {type: Boolean,default: true,},// 自定义类名customClass: {type: String,default: '',},
});const emit = defineEmits(['action', 'close']);const typeConfig = {info: { icon: InfoFilled, color: '#409eff', bg: 'linear-gradient(135deg, #ecf5ff 0%, #f0f7ff 100%)', border: '#d4e3ff' },success: { icon: SuccessFilled, color: '#67c23a', bg: 'linear-gradient(135deg, #f0f9eb 0%, #f5fbf0 100%)', border: '#e1f3d8' },warning: { icon: WarningFilled, color: '#e6a23c', bg: 'linear-gradient(135deg, #fdf6ec 0%, #fef9f0 100%)', border: '#faecd8' },error: { icon: CircleCloseFilled, color: '#f56c6c', bg: 'linear-gradient(135deg, #fef0f0 0%, #fef5f5 100%)', border: '#fde2e2' },
};const typeIcon = computed(() => typeConfig[props.type].icon);const alertClasses = computed(() => {return [`smart-alert--${props.type}`,{'smart-alert--closable': props.closable,'smart-alert--no-icon': !props.showIcon,},props.customClass,];
});const alertStyles = computed(() => {const config = typeConfig[props.type];return {'--alert-color': config.color,'--alert-bg': config.bg,'--alert-border': config.border,};
});const handleAction = () => {emit('action');
};const handleClose = () => {emit('close');
};
</script><style scoped lang="less">
.smart-alert {display: flex;align-items: flex-start;justify-content: space-between;padding: 16px;background: var(--alert-bg, linear-gradient(135deg, #ecf5ff 0%, #f0f7ff 100%));border: 1px solid var(--alert-border, #d4e3ff);border-radius: 8px;box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);transition: all 0.3s ease;.alert-content {display: flex;align-items: flex-start;flex: 1;gap: 12px;.alert-icon {display: flex;align-items: center;color: var(--alert-color, #409eff);font-size: 18px;margin-top: 1px;flex-shrink: 0;:deep(svg) {width: 1em;height: 1em;}}.alert-message {flex: 1;.alert-title {color: var(--alert-color, #409eff);font-size: 14px;font-weight: 600;line-height: 1.4;margin-bottom: 4px;}.alert-description {color: #606266;font-size: 14px;line-height: 1.5;word-break: break-word;:deep(*) {margin: 0;}}}}.alert-actions {display: flex;align-items: flex-start;gap: 8px;flex-shrink: 0;margin-left: 12px;:deep(.el-button) {color: var(--alert-color, #409eff);font-size: 14px;padding: 4px 8px;height: auto;&:hover {background: rgba(var(--alert-color-rgb), 0.1);}&.alert-close {color: #909399;&:hover {background: rgba(144, 147, 153, 0.1);}}}}// 无图标样式&.smart-alert--no-icon {.alert-content {.alert-icon {display: none;}}}
}// 类型样式
.smart-alert--info {--alert-color: #409eff;--alert-bg: linear-gradient(135deg, #ecf5ff 0%, #f0f7ff 100%);--alert-border: #d4e3ff;
}.smart-alert--success {--alert-color: #67c23a;--alert-bg: linear-gradient(135deg, #f0f9eb 0%, #f5fbf0 100%);--alert-border: #e1f3d8;
}.smart-alert--warning {--alert-color: #e6a23c;--alert-bg: linear-gradient(135deg, #fdf6ec 0%, #fef9f0 100%);--alert-border: #faecd8;
}.smart-alert--error {--alert-color: #f56c6c;--alert-bg: linear-gradient(135deg, #fef0f0 0%, #fef5f5 100%);--alert-border: #fde2e2;
}
</style>
父组件中使用
<SmartAlert type="success"title="操作成功" message="您的作品已成功发布" action-text="查看作品"closable@action="handleViewWork"@close="handleClose"/>
当然以上涉及的方法都可以不用的
也可以只显示一个 message 信息
