手写一个原生JS弹窗消息提醒插件

手写一个原生JS弹窗消息提醒插件

喏,就是这么一个效果。

具体功能:

  1. 当消息被触发的时候,会有一个自上而下的淡入过程。
  2. 在持续了一段时间后会自动的消失,或者是需要用户来手动的点击关闭按钮。
  3. 在消息消失的时候,会有一个自下而上的淡出过程。
  4. 消息是可以叠加弹出的,最新的消息会排在消息列表的最后面。
  5. 当前面的消息消失后,后面的消息会有一个向上滑动效果。

message.html

<!-- message.html -->

<!-- 这个css是我引用阿里的一些字体图标,请戳: https://www.iconfont.cn/ -->
<link rel="stylesheet" href="http://at.alicdn.com/t/font_1117508_wxidm5ry7od.css">
<link rel="stylesheet" href="./message.css">
<script src="./message.js"></script>

<!-- 消息外层容器,因为消息提醒基本上是全局的,所以这里用id,所有的弹出消息都是需要插入到这个容器里边的 -->
<div id="message-container">
    <div class="message">
        <!-- 消息图标 icon icon-success对应我的阿里字体图标的font-class -->
        <div class="type icon icon-success"></div>
        <!-- 消息文本 -->
        <div class="text">这是一条正经的消息~</div>
        <!-- 关闭按钮 -->
        <div class="close icon icon-close"></div>
    </div>
    <div class="message">
        <div class="type icon icon-error"></div>
        <div class="text">这是一条正经的消息~</div>
    </div>
</div>

message.css

#message-container {
    position: fixed;
    left: 0;
    top: 0;
    right: 0;
    z-index: 10000;

    /* 采用flex弹性布局,让容器内部的所有消息可以水平居中,还能任意的调整宽度 */
    display: flex;
    flex-direction: column;
    align-items: center;
}

#message-container .message {
    background: #fff;
    margin: 10px 0;
    padding: 0 10px;
    height: 40px;
    box-shadow: 0 0 10px 0 #ccc;
    font-size: 14px;
    border-radius: 3px;

    /* 让消息内部的三个元素(图标、文本、关闭按钮)可以垂直水平居中 */
    display: flex;
    align-items: center;
}

#message-container .message .text {
    color: #333;
    padding: 0 20px 0 5px;
}

#message-container .message .close {
    cursor: pointer;
    color: #999;
}

/* 给每个图标都加上不同的颜色,用来区分不同类型的消息 */
#message-container .message .iconicon-info {
    color: #0482f8;
}

#message-container .message .iconicon-error {
    color: #f83504;
}

#message-container .message .iconicon-success {
    color: #06a35a;
}

#message-container .message .iconicon-warning {
    color: #ceca07;
}

#message-container .message .iconicon-loading {
    color: #0482f8;
}

@keyframes message-move-in {
    0% {
        /* 前边分析过了,弹出动画是一个自上而下的淡入过程 */
        /* 所以在动画初始状态要把元素的不透明度设置为0,在动画结束的时候再把不透明度设置1,这样就会实现一个淡入动画 */
        opacity: 0;
        /* 那么“自上而下”这个动画可以用“transform”变换属性结合他的“translateY”上下平移函数来完成 */
        /* translateY(-100%)表示动画初始状态,元素在实际位置上面“自身一个高度”的位置。 */
        transform: translateY(-100%);
    }
    100% {
        opacity: 1;
        /* 平移到自身位置 */
        transform: translateY(0);
    }
}

#message-container .message.move-in {
    /* animation属性是用来加载某个动画规则 请参考 https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation */
    animation: message-move-in 0.3s ease-in-out;
}

@keyframes message-move-out {
    0% {
        opacity: 1;
        transform: translateY(0);
    }
    100% {
        opacity: 0;
        transform: translateY(-100%);
    }
}

#message-container .message.move-out {
    animation: message-move-out 0.3s ease-in-out;
    /* 让动画结束后保持结束状态 */
    animation-fill-mode: forwards;
}

message.js

class Message {
    /**
     * 构造函数会在实例化的时候自动执行
     */
    constructor() {
        const containerId = 'message-container';
        // 检测下html中是否已经有这个message-container元素
        this.containerEl = document.getElementById(containerId);

        if (!this.containerEl) {
            // 创建一个Element对象,也就是创建一个id为message-container的dom节点
            this.containerEl = document.createElement('div');
            this.containerEl.id = containerId;
            // 把message-container元素放在html的body末尾
            document.body.appendChild(this.containerEl);
        }
    }

    show({type = 'info', text = ''}) {
        // 创建一个Element对象
        let messageEl = document.createElement('div');
        // 设置消息class,这里加上move-in可以直接看到弹出效果
        messageEl.className = 'message move-in';
        // 消息内部html字符串
        messageEl.innerHTML = `
            <span class="iconfont iconicon-${type}"></span>
            <div class="text">${text}</div>
            <div class="close icon icon-close"></div>
            `;
        // 追加到message-container末尾
        // this.containerEl属性是我们在构造函数中创建的message-container容器
        this.containerEl.appendChild(messageEl);
        setTimeout(() => {
            // 首先把move-in这个弹出动画类给移除掉,要不然会有问题,可以自己测试下
            messageEl.className = messageEl.className.replace('move-in', '');
            // 增加一个move-out类
            messageEl.className += 'move-out';

            // 这个地方是监听动画结束事件,在动画结束后把消息从dom树中移除。
            // 如果你是在增加move-out后直接调用messageEl.remove,那么你不会看到任何动画效果
            messageEl.addEventListener('animationend', () => {
                // Element对象内部有一个remove方法,调用之后可以将该元素从dom树种移除!
                messageEl.remove();
            });
        }, 1500);
    }
}

调用

const message = new Message();
message.show({type: 'success', text: '这是成功的消息' })

本文原创作者:Laravuel,原文链接:https://www.jianshu.com/p/230810ef6543

给TA打赏
共{{data.count}}人
人已打赏
Vue

Vue如何实现点击复制功能?

2021-7-26 1:03:18

JavaScript

JS数组对象去重(4种方法)

2020-12-3 14:07:26

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索