亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

如何用原生js寫一個彈窗消息提醒插件

2024-05-06 16:51:23
字體:
來源:轉載
供稿:網友

1.分析

當消息被觸發的時候,會有一個自上而下的淡入過程。
在持續了一段時間后會自動的消失,或者是需要用戶來手動的點擊關閉按鈕。
在消息消失的時候,會有一個自下而上的淡出過程。
消息是可以疊加彈出的,最新的消息會排在消息列表的最后面。
當前面的消息消失后,后面的消息會有一個向上滑動效果。
然后消息本身是有三部分組成

消息圖標,用來區分不同類型的消息。
消息文本。
關閉按鈕,并不是所有消息都需要關閉按鈕。

2. 實現樣式

那么,不管我們是用原生js還是vue,首先呢,我們都需要把這個消息的基本樣式給寫出來,然后再通過js來控制消息的彈出和關閉。
所以,我們先來寫html和css。

<!-- 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" rel="external nofollow" ><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; /* 采用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 #eee; 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 .icon-info { color: #0482f8;}#message-container .message .icon-error { color: #f83504;}#message-container .message .icon-success { color: #06a35a;}#message-container .message .icon-warning { color: #ceca07;}#message-container .message .icon-loading { color: #0482f8;}

3. 實現動畫

接下來要做的就是這個消息的彈出和消失動畫,我們還是用css來實現。

想要在css里邊實現自定義的動畫,首先需要用@keyframes來定義一個動畫規則,然后再通過animation屬性把動畫應用到某個元素上就可以了。
所謂的動畫規則其實就是一個動畫序列,或者可以理解為一個個的關鍵幀,而關鍵幀的內部就是你想改變的css屬性,你可以在關鍵幀里邊寫上幾乎任何的css屬性,當動畫被應用的時候,這些css屬性就會根據各個關鍵幀做出相應的變換。

那我們先用@keyframes來寫一個動畫規則吧

/* 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元素同級的類move-in,把message-move-in這個動畫規則給應用到move-in類上,這樣我們需要讓哪個消息彈出,就只需要在消息的類上加一個move-in就行。

/* message.css */ #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;}

可以看到,只需要在某個message上追加一個move-in就能實現彈出動畫。
那么,消失動畫也是一個套路,只不過跟彈出動畫反過來而已。

/* message.css */ @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;}

animation-fill-mode: forwards;這個是干嘛的呢?因為動畫結束后默認會回到元素的最初狀態,在這里表現的是消失后又出現了。 

所以animation-fill-mode: forwards;是為了讓動畫結束后保持這個結束狀態,也就是不在顯示了。

4. 編寫js插件

那么,在寫js之前呢,我們先來思考一下,如果你是插件的使用者,你想怎么來調用這個插件?
我們的插件很簡單,就是在需要的時候彈出一個消息,假設插件他提供給我們的是一個類,就叫做Message吧,并且他內部有一個show方法,那么只要使用者實例化這個類后,調用他的show方法,然后傳入不同的參數就可以彈出一個消息了。而且我們所實例化的對象可以是全局唯一的。

<!-- message.html --><!-- 省略... --> <script>// message可以定義為全局對象,項目中可以直接調用。const message = new Message();message.show({ type: 'success', text: '點個關注不迷路~'});</script>

所以呢,我們要先寫一個Message類,并且必須要實現一個show方法。

/* message.js */ class Message { constructor() { } show({ type = 'info', text = '' }) { }}

這里我直接用了es6的class關鍵詞,其實他的內部還是原型鏈的形式。用class呢,可以讓我們更直觀的了解這個類。

根據我們在第一部分的分析,所有的消息元素都是需要在js中創建的,所以我們不需要使用者來寫任何html代碼,那么我們只需要在對象被實例化new Message()的時候,就去創建消息容器message-container,后續在調用show方法時候,直接把消息插入到message-container內部即可。

/* 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 = '' }) { }}

這樣,我們調用const message = new Message()的時候會在dom中自動的插入一個message-container節點。
那么,最重要的還是我們的show方法:

創建一個消息節點,并把它追加到message-container容器的末尾。
設定一個時間,在這個時間結束后自動的將消息移除。
監聽“關閉按鈕”的click事件,來讓用戶可以手動的移除消息。
我們一步一步來。

4.1 創建一個消息節點,并把它追加到message-container容器的末尾。

class Message { // 省略... show({ type = 'info', text = '' }) { // 創建一個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> <div class="close icon icon-close"></div> `; // 追加到message-container末尾 // this.containerEl屬性是我們在構造函數中創建的message-container容器 this.containerEl.appendChild(messageEl); }

我們來調用下試試~

 

<!-- message.html --><!-- 省略... --> <button class="btn">彈窗消息提醒</button> <script> // message可以定義為全局對象,項目中可以直接調用。 const message = new Message(); document.querySelector('.btn').addEventListener('click', () => { message.show({ type: 'success', text: '點個關注不迷路~' }); }); </script>

4.2 設定一個時間,在這個時間結束后自動的將消息移除。

// message.js class Message { // 省略... show({ type = 'info', text = '', duration = 2000 }) { // 省略... // 用setTimeout來做一個定時器 setTimeout(() => { // Element對象內部有一個remove方法,調用之后可以將該元素從dom樹種移除! messageEl.remove(); }, duration); }}

 可以看到,消息在過了2秒后,自動的從dom樹中移除了,不過呢并沒有動畫,還記得前邊我們寫了move-out類嗎?這個類和message是同級的?,F在我們只需要在定時結束后把這個類應用到message元素上就行。

// message.js class Message { // 省略... show({ type = 'info', text = '', duration = 2000 }) { // 省略... // 用setTimeout來做一個定時器 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(); }); }, duration); }}

4.3 監聽“關閉按鈕”的click事件,來讓用戶可以手動的移除消息。

有時候呢,我們希望消息能夠一直展示,直到用戶來手動的關閉掉,那么首先我們要加一個參數,用來控制是否展示這個關閉按鈕。

// message.js class Message { // 省略... show({ type = 'info', 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 (closeable) { // 創建一個關閉按鈕 let closeEl = document.createElement('div'); closeEl.className = 'close icon icon-close'; // 把關閉按鈕追加到message元素末尾 messageEl.appendChild(closeEl); // 監聽關閉按鈕的click事件,觸發后將調用我們的close方法 // 我們把剛才寫的移除消息封裝為一個close方法 closeEl.addEventListener('click', () => { 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(); }); }}
我們來調用下試試~
<!-- message.html --><!-- 省略... --> <button class="btn">彈窗消息提醒</button> <script> // message可以定義為全局對象,項目中可以直接調用。 const message = new Message(); document.querySelector('.btn').addEventListener('click', () => { message.show({ type: 'warning', text: '點我旁邊的叉叉試試', duration: 0, // 不會自動消失 closeable: true, // 可手動關閉 }); }); </script>

其實已經寫的差不多了,不過還是有一些小問題,比如當我們彈出兩個甚至更多消息的時候,如果前邊的消息消失后,下面的消息會直接跳到上面的位置,很僵硬,沒有任何的滑動。

我們可以通過css的transition屬性來讓meesage的高度逐漸變小,這樣下面的元素就會根據變化來逐漸上移。

/* message.css *//* 省略... */ #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元素的高度和margin變化時候將會有一個過渡動畫 */ transition: height 0.2s ease-in-out, margin 0.2s ease-in-out;} /* 省略... */
然后我們只需要在Message類的close方法中做一下改變:
 close(messageEl) { // 首先把move-in這個彈出動畫類給移除掉,要不然會有問題,可以自己測試下 messageEl.className = messageEl.className.replace('move-in', ''); // 增加一個move-out類 messageEl.className += 'move-out'; // move-out動畫結束后把元素的高度和邊距都設置為0 // 由于我們在css中設置了transition屬性,所以會有一個過渡動畫 messageEl.addEventListener('animationend', () => { messageEl.setAttribute('style', 'height: 0; margin: 0'); }); // 這個地方是監聽transition的過渡動畫結束事件,在動畫結束后把消息從dom樹中移除。 messageEl.addEventListener('transitionend', () => { // Element對象內部有一個remove方法,調用之后可以將該元素從dom樹種移除! messageEl.remove(); }); }

結尾
好了,基本上已經寫好了,不過為了各個瀏覽器的兼容性,建議大家用babel轉碼,如果想發布,可以用webpack把js和css一塊打包。
不過我們還是少考慮了一個場景,現在的關閉消息都是對象內部調用close方法來實現,如果我們希望外部能夠控制消息的關閉呢,比如我請求服務器時候彈出一個loading的消息,現在服務器返回數據后,我怎么來關閉這個消息呢。
很簡單,各位自行實現吧!

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品日韩久久久久| 精品色蜜蜜精品视频在线观看| 亚洲天堂开心观看| 欧美在线视频在线播放完整版免费观看| 国产亚洲人成a一在线v站| 久久在线视频在线| 欧美日韩ab片| 久久久久五月天| 国产精品大陆在线观看| 国产精品678| 青草青草久热精品视频在线观看| 欧美福利在线观看| 亚洲美女免费精品视频在线观看| 久久天天躁狠狠躁夜夜av| 久久香蕉国产线看观看av| 精品久久久国产| 欧美极品少妇全裸体| 亚洲国产精品视频在线观看| 一区二区三区视频免费在线观看| 九九热99久久久国产盗摄| 欧美性做爰毛片| 日韩电影中文字幕一区| 国内成人精品视频| 日韩在线视频二区| 欧美日韩一区二区三区| 亚洲国产精品久久久久| 日韩av在线天堂网| 日本人成精品视频在线| 国产精品网红直播| 午夜精品久久久久久99热| 日韩av在线最新| 国产日韩中文字幕在线| 亚洲国产精品久久91精品| 欧美国产亚洲精品久久久8v| 午夜精品99久久免费| 国产亚洲aⅴaaaaaa毛片| 亚洲国产精品久久| 亚洲欧美国产视频| 久久免费视频观看| 日韩电视剧在线观看免费网站| 中文字幕精品—区二区| 亚洲国产一区二区三区在线观看| 欧美日韩国产成人在线观看| 欧洲日本亚洲国产区| 国产精品成人品| 中文字幕日韩欧美精品在线观看| 欧美激情一区二区三级高清视频| 久久久伊人日本| 欧美性videos高清精品| 在线播放亚洲激情| 青青在线视频一区二区三区| 狠狠色噜噜狠狠狠狠97| 免费99精品国产自在在线| 成人国产精品一区| 国产一区二中文字幕在线看| 午夜精品三级视频福利| 欧美天天综合色影久久精品| 国产精品网站大全| 91精品国产高清久久久久久| 精品欧美国产一区二区三区| 亚洲精品久久久久久久久久久久久| 国产精品久久久久久av下载红粉| 69av成年福利视频| 亚洲欧美成人一区二区在线电影| 亚洲精品成人网| 日韩免费在线电影| 国产精品视频区1| 色综合伊人色综合网站| 久久的精品视频| 国内久久久精品| 国产成人久久久| 国产成人亚洲综合91精品| 成人日韩在线电影| 国产精品18久久久久久首页狼| 色综合伊人色综合网| 777国产偷窥盗摄精品视频| 亚洲永久免费观看| 久久91精品国产91久久跳| 国产成人精品网站| 欧美—级高清免费播放| 欧美激情一区二区三区在线视频观看| 欧美日韩aaaa| 久久中文字幕在线视频| 最近中文字幕日韩精品| 久久精品精品电影网| www.国产一区| 91国产精品视频在线| 亚洲欧美精品一区| 91夜夜未满十八勿入爽爽影院| 欧美性猛xxx| 亚洲视频网站在线观看| 色青青草原桃花久久综合| 欧洲精品在线视频| 久久欧美在线电影| 久久精品亚洲一区| 亚洲午夜精品久久久久久性色| 日韩精品一区二区三区第95| 亚洲国产成人精品一区二区| 欧美插天视频在线播放| 国产精品一二三视频| 欧美国产欧美亚洲国产日韩mv天天看完整| 国产精品久久久久久av福利软件| 国产精品久久久久久影视| 午夜精品视频在线| 亚洲天堂第一页| 欧美—级a级欧美特级ar全黄| 性色av一区二区三区红粉影视| 日韩在线播放一区| 日韩动漫免费观看电视剧高清| 最近2019免费中文字幕视频三| 亚洲一区二区三区毛片| 色香阁99久久精品久久久| 亚洲免费精彩视频| 亚洲aⅴ日韩av电影在线观看| 亚洲国产精品电影在线观看| 69国产精品成人在线播放| 久久精彩免费视频| 青青草一区二区| 亚洲高清色综合| 伊人久久久久久久久久| 亚洲深夜福利在线| 国产97在线播放| 精品久久久久久| 一区二区成人精品| 亚洲精品国产精品乱码不99按摩| 91麻豆国产语对白在线观看| 国产视频久久网| 亚洲欧美日韩一区二区在线| 国产精品电影网| 精品国产欧美一区二区五十路| 日韩免费不卡av| 日韩在线国产精品| 国产成人精品免高潮费视频| 欧美成人激情视频免费观看| 91理论片午午论夜理片久久| 国产精品jizz在线观看麻豆| 久久中文字幕在线视频| 欲色天天网综合久久| 8x海外华人永久免费日韩内陆视频| 欧美大片va欧美在线播放| 色偷偷亚洲男人天堂| 日韩av电影手机在线| 欧美日韩福利在线观看| 久久久久女教师免费一区| 国产精品中文字幕久久久| www.午夜精品| 成人亚洲激情网| 久久成人在线视频| 另类少妇人与禽zozz0性伦| 色哟哟入口国产精品| 91影院在线免费观看视频| 欧美日韩国产中字| 国产午夜精品全部视频播放| 亚洲性夜色噜噜噜7777| 日韩av在线影院| 国产成人亚洲精品| 国产精品欧美亚洲777777| 日韩精品极品视频免费观看| 国产97在线观看| 亚洲欧美日韩区| 中文字幕av一区| 97久久精品人搡人人玩| 91久久国产精品| 久久99精品久久久久久青青91|