发布于 

仿ElMessage,自行封装一个全局message消息提醒

仿照element-plus的message消息提醒,自行封装一个简化版的全局message消息提醒

实现功能:

  • 可以选择类型,如success、warning、error
  • 通过vue插件或函数使用

但多次触发消息提示,只有一个消息提示框,目前还没实现多次触发弹出多个提示框

实现代码如下:

src/components/Message/index.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<template>
<!-- message消息提示 -->
<div
v-if="showMessage"
:class="[
'message-box',
activeClass,
showMessage ? 'message-box-active' : '',
]"
>
<div class="message-body">
<span class="icon">{{ icon }}</span>
<span class="text">{{ messageText }}</span>
</div>
</div>
</template>

<script setup>
import { ref } from "vue";
const showMessage = ref(false);
const activeClass = ref("");
const time = ref(0);
const messageText = ref("");
const icon = ref("");
const iconType = {
success: "√",
warning: "!",
error: "×",
};

const handlerShow = ({
type = "success",
duration = 3000,
text = "消息提示",
}) => {
//展示提示框
showMessage.value = true;
//什么类型的提示框
activeClass.value = type;
//根据类型展示icon
icon.value = iconType[type]
//提示内容
messageText.value = text;
//持续时间
time.value = duration;
//定时器关闭
setTimeout(() => {
showMessage.value = false;
}, time.value);
};

//将handlerShow暴露出去
defineExpose({
handlerShow,
});
</script>

<style lang="scss">
.message-box {
position: fixed;
top: 0;
z-index: 9;
min-width: 300px;
border-radius: 4px;
border: 1px solid #ebeef5;
left: 50%;
transform: translateX(-50%);
overflow: hidden;
padding: 15px 15px 15px 20px;
opacity: 0;
transition: opacity 0.3s, transform 0.4s, top 0.4s;
.message-body {
display: flex;
align-items: center;
}
.text {
font-size: 14px;
}
.icon {
display: inline-block;
text-align: center;
width: 20px;
height: 20px;
text-align: center;
// padding: 5px;
line-height: 20px;
color: white;
border-radius: 50%;
font-size: 12px;
margin-right: 10px;
}
}
.message-box-active {
opacity: 1;
top: 10vh;
}
.success {
background: #f0f9eb;
border-color: #e1f3d8;
.text {
color: #52ac25;
}
.icon {
background: #52ac25;
}
}
.warning {
background: #fdf6ec;
border-color: #faecd8;
.text {
color: #e6a23c;
}
.icon {
background: #e6a23c;
}
}
.error {
background: #fef0f0;
border-color: #fde2e2;
.text {
color: #f56c6c;
}
.icon {
background: #f56c6c;
}
}
</style>

src/components/Message/index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import Message from './index.vue'
import { createVNode, render } from 'vue'

//导出对象,对象里面必须要有install方法,才能使用app.use()
export default {
//插件访问
install(app) {
//创建虚拟dom
const Vnode = createVNode(Message);
//将Message挂载在body下
render(Vnode, document.body);
//添加全局property,供全局访问
app.config.globalProperties.$message = Vnode.component.exposed.handlerShow
},

//函数访问
service({
type = "success",
duration = 3000,
text = "消息提示",
}) {
const vm = createVNode(Message);
//将vm挂载在body下
render(vm, document.body);
//调用组件
vm.component.exposed.handlerShow({type,duration,text})
}

//在组件中使用(插件)
// ...$message({
// type:'success',
// text:'成功了',
// duration:3000
// })
//函数使用
// import Message from "./components/Message"
// Message.service({
// type:'success',
// text:"成功",
// duration:2000
// })
}

src/main.js(如果当作插件来使用就需要app.use(…))

1
2
3
import Message from './components/Message'
...
app.use(Message)