特性
- type: 类型danger、info
- 主题: light、dark;
- close按钮、同时可以触发自定义close事件;
- 图标;
- 描述
实现思路
整体实现思路上不难;
- 对于不同类型、主题用 css 变量实现
代码
接下来看下代码实现:
类型 type.ts:
typescript
export type AlertType = "success" | "info" | "warning" | "danger";
export interface AlertProps {
title?: string;
type?: AlertType;
description?: string;
effect?: "light" | "dark";
closable?: boolean;
center?: boolean;
showIcon?: boolean;
}
export interface AlertEmits {
(e: "close"): void;
}
export interface AlertInstance {
open(): void;
close(): void;
}
主文件:
vue
<script setup lang="ts">
import type { AlertProps, AlertEmits, AlertInstance } from "./types";
import { typeIconMap } from "@toy-element/utils";
import { computed, ref } from "vue";
import ErIcon from "../Icon/Icon.vue";
defineOptions({
name: "ErAlert",
});
const props = withDefaults(defineProps<AlertProps>(), {
effect: "light",
type: "info",
closable: true,
});
const emits = defineEmits<AlertEmits>();
const slots = defineSlots();
const visible = ref(true);
const iconName = computed(() => typeIconMap.get(props.type) ?? "circle-info");
const withDescription = computed(() => props.description || slots.default);
function close() {
visible.value = false;
emits("close");
}
function open() {
visible.value = true;
}
defineExpose<AlertInstance>({
close,
open,
});
</script>
<template>
<transition name="er-alert-fade">
<div
v-show="visible"
class="er-alert"
role="alert"
:class="{
[`er-alert__${type}`]: type,
[`er-alert__${effect}`]: effect,
'text-center': center,
}"
>
<er-icon
v-if="showIcon"
class="er-alert__icon"
:class="{ 'big-icon': withDescription }"
:icon="iconName"
/>
<div class="er-alert__content">
<span
class="er-alert__title"
:class="{ 'with-desc': withDescription }"
:style="{ display: center && !showIcon ? 'flow' : 'inline' }"
>
<slot name="title">{{ title }}</slot>
</span>
<p class="er-alert__description">
<slot>{{ description }}</slot>
</p>
<div class="er-alert__close" v-if="closable">
<er-icon @click.stop="close" icon="xmark" />
</div>
</div>
</div>
</transition>
</template>
<style scoped>
@import "./style.css";
</style>
收获
关于代码测试的一些写法:
vue-test-utils 的 mount 函数