消息提示框在實際應用場景當中比較常見,最經常使用的就是element ui的消息提示框,咱們一般都是直接使用它們,可是咱們有沒有嘗試過去探究其實現原理,並本身動手實現呢?爲了提高咱們的我的能力和競爭力,咱們能夠嘗試來實現這樣一個消息提示框。css
咱們來查看一下最終實現效果,以下圖所示:html
咱們建立一個message文件夾,而後建立一個index.html文件,以及message.js和message.css文件,以下所示:es6
在html文件中,咱們能夠先來實現一個靜態的消息提示框,代碼以下:編程
<div class="message">
<p>這是一個提示框</p>
<i class="message-close-btn">×</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">×</i>
</div>
複製代碼
而後再css文件中加一段以下的css代碼便可:佈局
/* 內容居中 */
.message.message-center {
justify-content: center;
}
複製代碼
四種類型的提示框不外乎也是一樣的原理,增長一個類名,而後改變的是背景色和字體色,因此html代碼以下:字體
<div class="message message-success">
<p>這是一個成功提示框</p>
<i class="message-close-btn">×</i>
</div>
<div class="message message-warning">
<p>這是一個警告提示框</p>
<i class="message-close-btn">×</i>
</div>
<div class="message message-error">
<p>這是一個錯誤提示框</p>
<i class="message-close-btn">×</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 = '×';
//建立內容元素
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,而後不讓消息提示框重疊在一塊兒。代碼以下:
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';
}
}
複製代碼
咱們想要這樣調用$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中。
如此一來,咱們就完成了一個消息提示框。
若是以上分析還不懂的話,能夠查看我錄製的一個視頻: