從零開始實現一個消息提示框

引言

消息提示框在實際應用場景當中比較常見,最經常使用的就是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代碼:app

* {
    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消息提示框容器元素加上一個類名,代碼以下:函數

<div class="message message-center">
    <p>這是一個提示框</p>
    <i class="message-close-btn">&times;</i>
</div>

而後再css文件中加一段以下的css代碼便可:佈局

/* 內容居中 */
.message.message-center {
    justify-content: center;
}

四種類型的提示框不外乎也是一樣的原理,增長一個類名,而後改變的是背景色和字體色,因此html代碼以下:字體

<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代碼以下:flex

/* 成功提示框樣式 */
.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代碼,嘗試將如上代碼註釋掉。ui

動態實現建立提示框

定義四種類型的消息提示框

咱們經過定義一個對象來表示消息提示框的類型,以下所示:

// 消息提示框的四種類型
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中。

如此一來,咱們就完成了一個消息提示框。

錄製視頻

若是以上分析還不懂的話,能夠查看我錄製的一個視頻:

從零開始實現一個消息提示框

相關文章
相關標籤/搜索