摘要:前言項目中,當需要用戶處理事務,又不希望跳轉頁面以致打斷工作流程時,我們會經常使用到對話框去承載相應的操作。雖然用得多,但是很多人其實并不知道怎么去寫。饒有興趣,自己嘗試寫了一個。
前言
項目中,當需要用戶處理事務,又不希望跳轉頁面以致打斷工作流程時,我們會經常使用到對話框去承載相應的操作。雖然用得多,但是很多人其實并不知道怎么去寫。饒有興趣,自己嘗試寫了一個。
API參數 | 說明 | 類型 | 默認值 |
---|---|---|---|
afterClose | Modal 完全關閉后的回調 | function | 無 |
cancelText | 取消按鈕文字 | string | 取消 |
closable | 是否顯示右上角的關閉按鈕 | boolean | true |
destroyOnClose | 關閉時銷毀 Modal | boolean | false |
footer | 底部內容,當不需要默認底部按鈕時,可以設為 false | boolean | true |
maskClosable | 點擊蒙層是否允許關閉 | boolean | true |
okText | 確認按鈕文字 | string | 確定 |
title | 標題 | string|html節點 | 標題 |
width | 寬度 | number | 500 |
zIndex | 設置 Modal 的 z-index | number | 1000 |
keyboard | 是否支持鍵盤esc關閉 | boolean | true |
onCancel | 點擊遮罩層或右上角叉或取消按鈕的回調 | function(e) | 無 |
onOk | 點擊確定回調 | function(e) | 無 |
參數 | 說明 | 使用形式 |
---|---|---|
set | 已覆蓋默認的形式,設置新的屬性,內部 Object.assign(this.options, newOptions) | model.set(newOptions) |
open | 打開對話框 | model.open() |
close | 關閉對話框 | model.close() |
destroy | 與close的區別在于,會從節點上刪除 | model.destroy() |
對話框全局中使用一個就夠了,為了防止生成多個對話框,我們使用單例構造
var Dialog = (function () { var instance; return function (options) { if (!instance) { instance = new Modal(options); } return instance; } })()
這里主要運用到了閉包中的特性
modal.js代碼
var Dialog = (function () { var instance; return function (options) { if (!instance) { instance = new Modal(options); } return instance; } })() class Modal { constructor(options) { //默認屬性 this.initOptions = { title: "標題", maskClosable: true, header: true, footer: true, closable: true, okText: "確 定", cancelText: "取 消", destroyOnClose: false, keyboard: true, zIndex: 1000, width: 500, afterClose: null } this.options = Object.assign({}, this.initOptions, options); this.instance = document.createElement("div");//節點實例,因為只需要一個模態框,這里設置節點就可以了 this.mounted = false; //是否掛載在節點上 } //處理模態框的點擊事件 _modalClick(e) { var className = e.target.className; //匹配類名,例如 帶有 class="modal-close" 的元素點擊可以關閉模態框 if (new RegExp("(s|^)modal-close(s|$)").test(className)) { this.cancel(); //關閉模態框 } else if (new RegExp("(s|^)modal-onOk(s|$)").test(className)) { this.onOk(); //執行確定按鈕的回調 } else if (new RegExp("(s|^)modal-container(s|$)").test(className)) { this.outSideClick(); //模態框外的點擊 } } //處理鍵盤ESC關閉 _escClose(e) { var code = e.keyCode; if (code === 27) { this.cancel(); } } //渲染模態框節點 render() { var modal = this.instance; modal.style.zIndex = this.options.zIndex; modal.className = "modal-container"; var closeIcon = this.options.closable ? `X` : ""; var header = this.options.header ? (this.options.header === true ? `${this.options.title} ${closeIcon}` : this.options.header) : ""; var footer = this.options.footer ? (this.options.footer === true ? ` ` : this.options.footer) : ""; modal.innerHTML = `${header}`; } //蒙層點擊關閉 outSideClick() { if (this.options.maskClosable) { this.close(); } } //處理監聽 listen() { this._modalClick = this._modalClick.bind(this); this.instance.addEventListener("click", this._modalClick); if(this.options.keyboard){ this._escClose = this._escClose.bind(this); window.addEventListener("keyup", this._escClose); } } cancel(){ if(typeof this.options.onCancel === "function"){ this.options.onCancel(); } this.close(); } //點擊確定回調 onOk() { this .options .onOkFn(); this.close(); } /****************** 提供的方法 ********************* */ //設置屬性 set(options) { Object.assign(this.options, options) this.render() } //打開模態框 open() { var modal = this.instance; //實例如果沒掛載 if (!this.mounted) { this.mounted = true; this.render(); document.body.appendChild(modal); this.listen() } removeClass(modal, "close"); addClass(modal, "open"); } //關閉模態框 close() { var modal = this.instance removeClass(modal, "open"); addClass(modal, "close"); if (this.options.destroyOnClose === true) { this.destroy(); } if (typeof this.options.afterClose === "function") { var afterClose = this.options.afterClose.bind(this); setTimeout(afterClose, 0); } } //從節點上移除模態框 destroy() { this.instance.removeEventListener("click", this._modalClick);//移除click監聽 window.removeEventListener("keyup", this._escClose);//移除keyup監聽 document.body.removeChild(this.instance);//移除模態框節點 this.mounted = false; } } function hasClass(elements, cName) { return !!elements .className .match(new RegExp("(s|^)" + cName + "(s|$)")); }; function addClass(elements, cName) { if (!hasClass(elements, cName)) { elements.className += " " + cName; }; }; function removeClass(elements, cName) { if (hasClass(elements, cName)) { elements.className = elements .className .replace(new RegExp("(s|^)" + cName + "(s|$)"), ""); }; }; ${footer}
modal.css
@keyframes openAnimate { 0% { opacity: 0; } 100%{ opacity: 1; } } .open{ display: block !important; animation: openAnimate .8s; } .close{ display: none; } .modal-container { position: fixed; top: 0; right: 0; left: 0; bottom: 0; background-color: #373737; background-color: rgba(0,0,0,.65); margin: auto; filter: alpha(opacity=50); text-align: center; font-size: 0; white-space: nowrap; overflow: auto; display: none; } .modal-container:after { content: ""; display: inline-block; height: 100%; vertical-align: middle; } .modal { display: inline-block; vertical-align: middle; text-align: left; font-size: 14px; background-color: #fff; border: 0; border-radius: 4px; background-clip: padding-box; box-shadow: 0 4px 12px rgba(0,0,0,.15); } .modal-header{ padding: 16px 24px; border-radius: 4px 4px 0 0; background: #fff; color: rgba(0,0,0,.65); border-bottom: 1px solid #e8e8e8; } .modal-close{ float: right; cursor: pointer; } .modal-content{ padding: 24px; font-size: 14px; line-height: 1.5; word-wrap: break-word; min-height: 200px; } .modal-footer { border-top: 1px solid #e8e8e8; padding: 10px 16px; text-align: right; border-radius: 0 0 4px 4px; } .modal-btn{ line-height: 32px; display: inline-block; font-weight: 400; text-align: center; touch-action: manipulation; cursor: pointer; background-image: none; border: 1px solid transparent; white-space: nowrap; padding: 0 15px; font-size: 14px; border-radius: 4px; height: 32px; user-select: none; transition: all .3s cubic-bezier(.645,.045,.355,1); position: relative; color: rgba(0,0,0,.65); background-color: #fff; border-color: #d9d9d9; cursor: pointer; } .modal-btn-primary{ color: #fff; background-color: #1890ff; border-color: #1890ff; }如何使用
Document
index.js
var config = { title: "模態框標題", content: "", header: true, footer: true, destroyOnClose: true, onOkFn: function () { alert("提交成功") }, afterClose: function(){ alert("已經關閉") } } var modal = new Dialog(config); var openBtns = document.querySelectorAll(".open"); openBtns.forEach(function (item, index) { item.onclick = function () { var option = { content: "這是第" + (index + 1) + "個" } modal.set(option) modal.open(); } })
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95423.html
摘要:總之,選擇單例模式就是為了避免不一致狀態,避免政出多頭。二餓漢式單例餓漢式單例類在類初始化時,已經自行實例化靜態工廠方法餓漢式在類創建的同時就已經創建好一個靜態的對象供系統使用,以后不再改變,所以天生是線程安全的。 概念: Java中單例模式是一種常見的設計模式,單例模式的寫法有好幾種,這里主要介紹兩種:懶漢式單例、餓漢式單例。 單例模式有以下特點: 1、單例類只能有一個實例。 ...
摘要:簡介單例模式是指整個應用中類只有一個對象實例的設計模式。它是一種常見的設計模式,在計算機系統中,線程池緩存日志對象對話框打印機數據庫操作顯卡的驅動程序常被設計成單例。 簡介 單例模式是指整個應用中類只有一個對象實例的設計模式。它通常被用來創建對象,確保某個類只有一個實例,而且自行實例化并向整個系統提供這個實例。 它是一種常見的設計模式,在計算機系統中,線程池、緩存、日志對象、對話框、打...
摘要:一單例模式定義單例模式確保某個類只有一個實例,而且自行實例化并向整個系統提供這個實例。技術實現單例模式靜態內部類評價使用靜態內部類的方式,只有在使用該實例的時候,才去加載靜態內部類,從而實現延時加載。 一、單例模式定義:單例模式確保某個類只有一個實例,而且自行實例化并向整個系統提供這個實例。在計算機系統中,線程池、緩存、日志對象、對話框、打印機、顯卡的驅動程序對象常被設計成單例。這些應...
摘要:會一直完善下去,歡迎建議和指導,同時也歡迎中用到了那些設計模式中用到了那些設計模式這兩個問題,在面試中比較常見。工廠設計模式使用工廠模式可以通過或創建對象。 我自己總結的Java學習的系統知識點以及面試問題,已經開源,目前已經 41k+ Star。會一直完善下去,歡迎建議和指導,同時也歡迎Star: https://github.com/Snailclimb... JDK 中用到了那...
摘要:總結我們主要介紹到了以下幾種方式實現單例模式餓漢方式線程安全懶漢式非線程安全和關鍵字線程安全版本懶漢式雙重檢查加鎖版本枚舉方式參考設計模式中文版第二版設計模式深入理解單例模式我是一個以架構師為年之內目標的小小白。 初遇設計模式在上個寒假,當時把每個設計模式過了一遍,對設計模式有了一個最初級的了解。這個學期借了幾本設計模式的書籍看,聽了老師的設計模式課,對設計模式算是有個更進一步的認識。...
閱讀 1669·2021-11-19 09:40
閱讀 2926·2021-09-24 10:27
閱讀 3215·2021-09-02 15:15
閱讀 1876·2019-08-30 15:54
閱讀 1202·2019-08-30 15:54
閱讀 1369·2019-08-30 13:12
閱讀 626·2019-08-28 18:05
閱讀 2794·2019-08-27 10:53