封装思路

  • 暴漏一个全局对象,内含四个方法->四个方法分别对应不同的消息提示类型
  • 方法可以接受一个字符串,或者接受一个指定类型的对象
  • 参数归一化
  • 使用 vue 的 createApp 创建一个临时组件进行挂载
  • 书写样式动画

封装效果

封装效果

实现过程

使用

<template>
<div class="container">
<div @click="success">SUCCESS</div>
<div @click="warning">WARNING</div>
<div @click="info">INFO</div>
<div @click="error">ERROR</div>
</div>
</template>

<script setup lang="ts">
import Message from "../libs/TS-UI/message/index";
const success = () => {
Message.success("this is success");
};
const warning = () => {
Message.warning("this is warning");
};
const info = () => {
Message.info({
message: "this is info",
});
};
const error = () => {
Message.error({
message: "this is error",
duration: 3000,
});
};
</script>

index.ts

import { info, success, error, warning } from "./ts/message";
import { MessageObject } from "./ts/types";
const Message = {
info,
success,
error,
warning,
} as MessageObject;

export default Message;

message.ts

import { MessageOptions } from "./types";
import { showMessage } from "./createApp";
import { normalizeOptions } from "./utils";
export const info = (obj: MessageOptions) => {
obj = normalizeOptions(obj);
showMessage(obj, "info");
};
export const error = (obj: MessageOptions) => {
obj = normalizeOptions(obj);
showMessage(obj, "error");
};
export const success = (obj: MessageOptions) => {
obj = normalizeOptions(obj);
showMessage(obj, "success");
};
export const warning = (obj: MessageOptions) => {
obj = normalizeOptions(obj);
showMessage(obj, "warning");
};

utils.ts

import { MessageOptions, Options } from "./types";

/** 参数归一化 */
export const normalizeOptions = (obj: MessageOptions) => {
let newObj: Options;
if (typeof obj === "string") {
newObj = { message: obj };
} else {
newObj = obj;
}
return newObj;
};

createApp.ts

import { createApp, h } from "vue";
import { MsgType, Options } from "./types";
import "../message.css";

/** 创建一个组件 内容会在 createApp 时注入进来 */
const messageBox = {
props: {
message: {
type: String,
required: true,
},
duration: {
type: Number,
default: 3000,
},
type: {
type: String,
required: true,
},
},
//渲染函数
render(ctx) {
const { $props } = ctx;
return h("div", { class: `base msg-${$props.type}` }, $props.message);
},
};
//调用函数渲染弹窗
export function showMessage(obj: Options, type: MsgType) {
//messageBox 组件内容 ,后面的对象就是给组件的props
const app = createApp(messageBox, {
message: obj.message,
duration: obj.duration,
type: type,
});
//元素挂载
const div = document.createElement("div");
const par = document.querySelector("#app") as HTMLDivElement;
par.appendChild(div);
app.mount(div);
setTimeout(() => {
app.unmount();
par.removeChild(div);
}, obj.duration || 2000);
}

message.css

.base {
padding: 20px;
position: relative;
z-index: 10000;
left: 50%;
transform: translate(-50%, -50%);
top: 0;
opacity: 0;
animation-duration: 1s;
animation-timing-function: ease;
animation-delay: 0s;
animation-name: fall;
background: rgba(255, 255, 255, 0.8);
border-radius: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
font-size: 20px;
min-width: 200px;
max-width: 500px;
max-height: 100px;
overflow: auto;
display: flex;
justify-content: center;
align-items: center;
}

@keyframes fall {
0% {
top: 0;
opacity: 0.5;
}
100% {
top: 100px;
opacity: 1;
}
}
.msg-info {
color: #333;
background-color: aliceblue;
}
.msg-error {
color: #fff;
background-color: #da5249;
}
.msg-success {
color: #fff;
background-color: #6ace6d;
}
.msg-warning {
color: #fff;
background-color: #d48b1c;
}