从零开始实现一个消息提示框

引言

消息提示框在实际应用场景当中比较常见,最经常使用的就是element ui的消息提示框,咱们一般都是直接使用它们,可是咱们有没有尝试过去探究其实现原理,并本身动手实现呢?为了提高咱们的我的能力和竞争力,咱们能够尝试来实现这样一个消息提示框。css

实现效果

咱们来查看一下最终实现效果,以下图所示:html

准备工做

搭建基本的项目结构

咱们建立一个message文件夹,而后建立一个index.html文件,以及message.js和message.css文件,以下所示:es6

对消息提示框进行布局

在html文件中,咱们能够先来实现一个静态的消息提示框,代码以下:编程

<div class="message">
    <p>这是一个提示框</p>
    <i class="message-close-btn">&times;</i>
</div>
复制代码

而后再message.css咱们写上基本的css代码:markdown

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
/* 消息提示框容器样式 */
.message {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    min-width: 300px;
    background-color: #edf2fc;
    border: 1px solid #edf2fc;
    padding: 16px 17px;
    top: 25px;
    border-radius: 6px;
    overflow: hidden;
    z-index: 1000;
}
/* 关闭按钮样式 */
.message > .message-close-btn {
    position: absolute;
    right: 15px;
    top: 50%;
    transform: translateY(-50%);
    color: #c0c0c4;
    font-size: 17px;
    cursor: pointer;
}
.message > .message-close-btn:hover,.message > .message-close-btn:active {
    color: #909399;
}
/* 消息提示框内容样式 */
.message p {
    line-height: 1;
    font-size:14px;
    color: #909399;
}
复制代码

有四种提示框,以及让内容居中,咱们不外乎是多加一个类名来写css样式,好比内容居中,咱们只须要在html消息提示框容器元素加上一个类名,代码以下:app

<div class="message message-center">
    <p>这是一个提示框</p>
    <i class="message-close-btn">&times;</i>
</div> 
复制代码

而后再css文件中加一段以下的css代码便可:函数

/* 内容居中 */
.message.message-center {
    justify-content: center;
}
复制代码

四种类型的提示框不外乎也是一样的原理,增长一个类名,而后改变的是背景色和字体色,因此html代码以下:oop

<div class="message message-success">
    <p>这是一个成功提示框</p>
    <i class="message-close-btn">&times;</i>
</div>
<div class="message message-warning">
    <p>这是一个警告提示框</p>
    <i class="message-close-btn">&times;</i>
</div>
<div class="message message-error">
    <p>这是一个错误提示框</p>
    <i class="message-close-btn">&times;</i>
</div>
复制代码

css代码以下:布局

/* 成功提示框样式 */
.message.message-success {
    background-color: #e1f3d8;
    border-color:#e1f3d8;
}
.message.message-success p {
    color: #67c23a;
}
/* 警告提示框样式 */
.message.message-warning{
    background-color: #fdfce6;
    border-color: #fdfce6;
}
.message.message-warning p{
    color: #e6a23c;
}
/* 错误提示框样式 */
.message.message-error {
    background-color: #fef0f0;
    border-color: #fef0f0;
}
.message.message-error p {
    color: #f56c6c;
}
复制代码

这样一来,准备工做就完成了,接下来就是咱们的重头戏,JavaScript代码,尝试将如上代码注释掉。字体

动态实现建立提示框

定义四种类型的消息提示框

咱们经过定义一个对象来表示消息提示框的类型,以下所示:

// 消息提示框的四种类型
let typeMap = {
    info: "info",
    warning: "warning",
    success: "success",
    error: "error"
}
复制代码

添加默认配置项

咱们分析一下须要传入的配置项有内容(content),关闭提示框时间(closeTime),是否显示关闭提示框按钮(showClose),内容居中(center)以及消息提示框类型(type)。因此定义配置项以下:

// 提示框的默认配置项
let messageOption = {
    type: "info",
    closeTime: 600,
    center: false,
    showClose: false,
    content: "默认内容"
}
复制代码

建立一个消息提示框类

咱们经过面向对象的编程思惟将消息提示框当作是一个类对象,因此咱们只须要建立一个类。虽然能够使用es6的class语法来建立,可是为了方便,咱们使用构造函数来实现。建立一个构造函数Message,以下所示:

function Message(option) {
    //这里作了一次初始化
    this.init(option);
}
复制代码

初始化

建立了消息提示框构造函数以后,咱们须要传入配置项,而且咱们在函数里作了初始化操做,接下来咱们来实现初始化的操做。

Message.prototype.init = function (option) {
    //这里建立了提示框元素,并将整个提示框容器元素添加到页面中
    document.body.appendChild(this.create(option));
    //这里设置提示框的top
    this.setTop(document.querySelectorAll('.message'));
    //判断若是传入的closeTime大于0,则默认关闭提示框
    if (option.closeTime > 0) {
        this.close(option.container, option.closeTime);
    }
    //点击关闭按钮关闭提示框
    if (option.close) {
        option.close.onclick = (e) => {
            this.close(e.currentTarget.parentElement, 0);
        }
    }
}
复制代码

建立提示框

在前面的初始化操做中,咱们作了几个功能,首先建立提示框容器元素,并将提示框容器元素添加到页面bod中。咱们还作了动态计算提示框的top以及判断传入的默认关闭时间来关闭提示框,点击关闭按钮关闭提示框。咱们来看建立提示框的方法,即create方法的编写操做。以下:

Message.prototype.create = function (option) {
    //这里作了一个判断,表示若是设置showClose为false即不显示关闭按钮而且closeTime也为0,即无自动关闭提示框,咱们就显示关闭按钮
    if(!option.showClose && option.closeTime <=0)option.showClose = true;
    //建立容器元素
    let element = document.createElement('div');
    //设置类名
    element.className = `message message-${option.type}`;
    if (option.center) element.classList.add('message-center');
    //建立关闭按钮元素以及设置类名和内容
    let closeBtn = document.createElement('i');
    closeBtn.className = 'message-close-btn';
    closeBtn.innerHTML = '&times;';
    //建立内容元素
    let contentElement = document.createElement('p');
    contentElement.innerHTML = option.content;
    //判断若是显示关闭按钮,则将关闭按钮元素添加到提示框容器元素中
    if (closeBtn && option.showClose) element.appendChild(closeBtn);
    //将内容元素添加到提示框容器中
    element.appendChild(contentElement);
    //在配置项对象中存储提示框容器元素以及关闭按钮元素
    option.container = element;
    option.close = closeBtn;
    //返回提示框容器元素
    return element;
}
复制代码

实现提示框的关闭

咱们能够看到,咱们建立了一个close方法,并传入提示框容器元素,来实现关闭一个提示框,接下来咱们来实现这个关闭方法。以下所示:

Message.prototype.close = function (messageElement, time) {
    //根据传入的时间来延迟关闭,实际上也就是移除元素
    setTimeout(() => {
        //判断若是传入了提示框容器元素,而且分两种状况,若是是多个提示框容器元素则循环遍历删除,若是是单个提示框容器元素,则直接删除
        if (messageElement && messageElement.length) {
            for (let i = 0; i < messageElement.length; i++) {
                if (messageElement[i].parentElement) {
                    messageElement[i].parentElement.removeChild(messageElement[i]);
                }
            }
        } else if (messageElement) {
            if (messageElement.parentElement) {
                messageElement.parentElement.removeChild(messageElement);
            }
        }
        //关闭了提示框容器元素以后,咱们从新设置提示框的top值
        this.setTop(document.querySelectorAll('.message'));
    }, time * 10);
}
复制代码

实现提示框的动态top

最后咱们须要实现的是动态计算消息提示框的top,而后不让消息提示框重叠在一块儿。代码以下:

Message.prototype.setTop = function (messageElement) {
    //这里作一个判断的缘由就是当点击页面中最后一个提示框的时候,会从新调用一次,这时获取不到提示框容器元素,因此就不执行后续的设置top
    if (!messageElement || !messageElement.length) return;
    //因为每一个提示框的高度同样,因此咱们只需获取第一个提示框元素的高度便可
    const height = messageElement[0].offsetHeight;
    for (let i = 0; i < messageElement.length; i++) {
        //每一个提示框的top由一个固定值加上它的高度,而且咱们要乘以它的一个索引值
        messageElement[i].style.top = (25 * (i + 1) + height * i) + 'px';
    }
}
复制代码

最后,实现封装,让咱们能够如同调用element ui那样来调用

咱们想要这样调用$message()或者$message.info(),那么咱们能够实现以下:

let $message = {};
window['$message'] = $message = function (option) {
    let newMessageOption = null;
    if (typeof option === 'string') {
        newMessageOption = Object.assign(messageOption, { content: option });
    } else if (typeof option === 'object' && !!option) {
        newMessageOption = Object.assign(messageOption, option);
    }
    return new Message(newMessageOption);
}
for (let key in typeMap) {
    window['$message'][key] = function (option) {
        let newMessageOption = null;
        if (typeof option === 'string') {
            newMessageOption = Object.assign(messageOption, { content: option,type:typeMap[key] });
        } else if (typeof option === 'object' && !!option) {
            newMessageOption = Object.assign(JSON.parse(JSON.stringify(messageOption)),option,{ type:typeMap[key] });
        }
        return new Message(newMessageOption);
    }
}
复制代码

整个逻辑也十分简单,无非就是判断传入的配置项,而后进行合并,并传入实例化的Message中。

如此一来,咱们就完成了一个消息提示框。

录制视频

若是以上分析还不懂的话,能够查看我录制的一个视频:

从零开始实现一个消息提示框
相关文章
相关标签/搜索