本片博文受到https://blog.csdn.net/zfzhuman123/article/details/90411793的啓發,es6部分代碼只改了一點點,邏輯也是遵照他的思想來的,而且es5繼承的部分也是用了部分es6的語法
1.首先是index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="http://at.alicdn.com/t/font_1117508_wxidm5ry7od.css">
<style>
/* message.css */
/* 這個動畫規則我們就叫做message-move-in吧,隨後我們會用animation屬性在某個元素上應用這個動畫規則。 */
@keyframes message-move-in {
0% {
/* 前邊分析過了,彈出動畫是一個自上而下的淡入過程 */
/* 所以在動畫初始狀態要把元素的不透明度設置爲0,在動畫結束的時候再把不透明度設置1,這樣就會實現一個淡入動畫 */
opacity: 0;
/* 那麼“自上而下”這個動畫可以用“transform”變換屬性結合他的“translateY”上下平移函數來完成 */
/* translateY(-100%)表示動畫初始狀態,元素在實際位置上面“自身一個高度”的位置。 */
transform: translateY(-100%);
}
100% {
opacity: 1;
/* 平移到自身位置 */
transform: translateY(0);
}
}
/* message.css */
@keyframes message-move-out {
0% {
opacity: 1;
transform: translateY(0);
}
100% {
opacity: 0;
transform: translateY(-100%);
}
}
/* message.css */
#message-container .message.move-in,
#container .message.move-in
{
/* animation屬性是用來加載某個動畫規則 請參考 https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation */
animation: message-move-in 0.3s ease-in-out;
/*ease-in-out 規定以慢速開始和結束的過渡效果(等於 cubic-bezier(0.42,0,0.58,1))(相對於勻速,(開始和結束都慢)兩頭慢)。*/
}
#message-container .message.move-out,
#container .message.move-out
{
animation: message-move-out 0.3s ease-in-out;
/* 讓動畫結束後保持結束狀態 */
animation-fill-mode: forwards;
}
/* message.css */
#message-container,
#container
{
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: #eee;
/* 採用flex彈性佈局,讓容器內部的所有消息可以水平居中,還能任意的調整寬度 */
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#message-container .message,
#container .message
{
background: #fff;
margin: 10px 0;
padding: 0 10px;
height: 40px;
box-shadow: 0 0 10px 0 #eee;
font-size: 14px;
border-radius: 3px;
/* 讓消息內部的三個元素(圖標、文本、關閉按鈕)可以垂直水平居中 */
display: flex;
align-items: center;
}
/* 給每個圖標都加上不同的顏色,用來區分不同類型的消息 */
.message .icon-info {
color: #0482f8;
}
.message .icon-error {
color: #f83504;
}
.message .icon-success {
color: #06a35a;
}
.message .icon-warning {
color: #ceca07;
}
.message .icon-loading {
color: #0482f8;
}
.btn {
position: absolute;
top: 10px;
left: 10px;
z-index: 100;
}
</style>
</head>
<body>
<button class="btn">彈窗消息提醒</button>
</body>
<script src="index.js"></script>
<script>
// message可以定義爲全局對象,項目中可以直接調用。
const message = new Message({
containerId: 'container'
});
document.querySelector('.btn').addEventListener('click', () => {
message.show({
type: 'error',
text: '點我旁邊的叉叉試試',
duration: 1000, // 不會自動消失
closeable: true, // 可手動關閉
});
});
</script>
</html>
2.es6部分
class Message {
//構造函數會在實例化的時候自動執行
constructor(opts={}) {
const containerId = opts.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 = 'success', text = '', duration = 2000, closeable = false }) {
// 創建一個Element對象
let messageEl = document.createElement('div');
// 設置消息class,這裏加上move-in可以直接看到彈出效果
messageEl.className = 'message move-in';
// 消息內部html字符串
messageEl.innerHTML = `
<span class="icon icon-${type}"></span>
<div class="text">${text}</div>
`;
//點擊彈窗提醒按鈕,不能多次出現彈窗
if(document.getElementsByClassName(messageEl.className).length>0) {
alert('彈窗已存在');
return;
}
// 是否展示關閉按鈕
if (closeable) {
// 創建一個關閉按鈕
let closeEl = document.createElement('div');
closeEl.className = 'close icon icon-close';
// 把關閉按鈕追加到message元素末尾
messageEl.appendChild(closeEl);
// 監聽關閉按鈕的click事件,觸發後將調用我們的close方法
// 我們把剛纔寫的移除消息封裝爲一個close方法
closeEl.addEventListener('click', (e) => {
this.close(messageEl)
});
}
// 追加到message-container末尾
// this.containerEl屬性是我們在構造函數中創建的message-container容器
this.containerEl.appendChild(messageEl);
// 只有當duration大於0的時候才設置定時器,這樣我們的消息就會一直顯示
if (duration > 0) {
// 用setTimeout來做一個定時器
setTimeout(() => {
//this.close(messageEl);
}, duration);
}
}
/**
* 關閉某個消息
* 由於定時器裏邊要移除消息,然後用戶手動關閉事件也要移除消息,所以我們直接把移除消息提取出來封裝成一個方法
* @param {Element} messageEl
*/
close(messageEl) {
// 首先把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();
});
}
}
3.es5方法
function Message(opts) {
var defaultOpts = {containerId: opts.containerId||'message-container'};
const containerId = defaultOpts.containerId;
// 檢測下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);
}
}
//彈窗出現
Message.prototype.show = function(opts) {
//es6的語法--解構賦值
var defaultOpts = {
type: opts.type||'success',
text: opts.text||'點我旁邊的叉叉試試',
duration: opts.duration||2000, // 不會自動消失
closeable: opts.closeable||true, // 可手動關閉
}
let {type,text,duration,closeable} = defaultOpts;
// 創建一個Element對象
let messageEl = document.createElement('div');
// 設置消息class,這裏加上move-in可以直接看到彈出效果
messageEl.className = 'message move-in';
// 消息內部html字符串
messageEl.innerHTML = `
<span class="icon icon-${type}"></span>
<div class="text">${text}</div>
`;
//點擊彈窗提醒按鈕,不能多次出現彈窗
if(document.getElementsByClassName(messageEl.className).length>0) {
alert('彈窗已存在');
return;
}
// 是否展示關閉按鈕
if (closeable) {
// 創建一個關閉按鈕
let closeEl = document.createElement('div');
closeEl.className = 'close icon icon-close';
// 把關閉按鈕追加到message元素末尾
messageEl.appendChild(closeEl);
// 監聽關閉按鈕的click事件,觸發後將調用我們的close方法
// 我們把剛纔寫的移除消息封裝爲一個close方法
closeEl.addEventListener('click', (e) => {
this.close(messageEl)
});
}
// 追加到message-container末尾
// this.containerEl屬性是我們在構造函數中創建的message-container容器
this.containerEl.appendChild(messageEl);
// 只有當duration大於0的時候才設置定時器,這樣我們的消息就會一直顯示
if (duration > 0) {
// 用setTimeout來做一個定時器
setTimeout(() => {
//this.close(messageEl);
}, duration);
}
}
//彈窗消失
Message.prototype.close = function(messageEl) {
// 首先把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();
});
}
然後各自將es6或者es5這部分js在index.html中使用script標籤引入,點擊按鈕查看效果就行了