前言
之前项目中有使用Ant Design组件库进行开发,觉得message全局提示的功能挺有意思的,就花了点时研究了一下。支持五种提示,分别是success,error,info,warning,loading。用户可以主动移除,也可设置延时自动移除。是一种不打断用户操作的轻量级提示方式。快来看一下如何实现的吧。
页面结构
<div class="overlay">
<ul class="message-list"></ul>
</div>
样式
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
/* 元素永远不会成为鼠标事件的target */
pointer-events: none;
}
.message-list {
position: fixed;
top: 30px;
left: 0;
right: 0;
list-style: none;
}
.message-item {
display: flex;
justify-content: center;
padding: 8px;
}
.message-item div {
display: flex;
align-items: center;
padding: 10px 16px;
background: #FFF;
border-radius: 2px;
box-shadow: 0 3px 6px -4px rgb(0 0 0 / 12%), 0 6px 16px 0 rgb(0 0 0 / 8%), 0 9px 28px 8px rgb(0 0 0 / 5%);
}
.message-item .icon {
width: 16px;
height: 16px;
margin-right: 10px;
}
/* loading旋转动画 */
.message-item .icon.loading {
animation: loading 1s linear infinite;
}
@keyframes loading {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.message-item div span {
font-size: 14px;
line-height: 20px;
}
.fade-in {
animation: fadeIn .3s ease forwards;
}
/* 淡入动画 */
@keyframes fadeIn {
0% {
opacity: 0;
transform: translateY(-100%);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
/* 淡出动画 */
.fade-out {
animation: fadeOut .3s ease forwards;
}
@keyframes fadeOut {
0% {
opacity: 1;
transform: translateY(0);
}
100% {
opacity: 0;
transform: translateY(-100%);
}
}
代码
/* 构造函数 */
function Message() { }
/* 用于移除message */
Message.id = 0;
/**
* 创建全局提示
* @param {string} content 提示内容
* @param {number} duration 持续时间
* @param {string} type 提示类型
*/
Message.prototype.create = function (content, duration, type) {
// svg太长,此处省略
const icon = {
success: '<svg class="icon success">...</svg>',
error: '<svg class="icon error">...</svg>',
info: '<svg class="icon info">...</svg>',
warning: '<svg class="icon warning">...</svg>',
loading: '<svg class="icon loading">...</svg>'
}
const html = `
<li class="message-item fade-in" data-id="${Message.id}">
<div>
${icon[type]}
<span>${content}</span>
</div>
</li>`;
ul.insertAdjacentHTML('beforeend', html);
Message.id++;
const lis = document.querySelectorAll('li.message-item');
const length = lis.length;
const lastLi = lis[length - 1];
// 延时移除
lastLi._timeout = setTimeout(function () {
lastLi.classList.remove('fade-in');
lastLi.classList.add('fade-out');
lastLi.addEventListener('animationend', function (e) {
this.remove();
});
}, duration);
// 最多显示7条
if (length > 7) {
clearTimeout(lis[0]._timeout);
lis[0].remove();
}
}
Message.prototype.success = function (content, duration = 3000) {
this.create(content, duration, 'success');
return Message.id;
}
Message.prototype.error = function (content, duration = 3000) {
this.create(content, duration, 'error');
return Message.id;
}
Message.prototype.warning = function (content, duration = 3000) {
this.create(content, duration, 'warning');
return Message.id;
}
Message.prototype.info = function (content, duration = 3000) {
this.create(content, duration, 'info');
return Message.id;
}
Message.prototype.loading = function (content, duration = 3000) {
this.create(content, duration, 'loading');
return Message.id;
}
Message.prototype.remove = function (id) {
const li = document.querySelector(`li.message-item[data-id="${id}"]`);
clearTimeout(li._timeout);
li.remove();
}
// 调用
const message = new Message();
const id = message.success('This is a message of success');
// 移除
message.remove(id);