摘要:前言項(xiàng)目中,當(dāng)需要用戶處理事務(wù),又不希望跳轉(zhuǎn)頁面以致打斷工作流程時(shí),我們會(huì)經(jīng)常使用到對(duì)話框去承載相應(yīng)的操作。雖然用得多,但是很多人其實(shí)并不知道怎么去寫。饒有興趣,自己嘗試寫了一個(gè)。
前言
項(xiàng)目中,當(dāng)需要用戶處理事務(wù),又不希望跳轉(zhuǎn)頁面以致打斷工作流程時(shí),我們會(huì)經(jīng)常使用到對(duì)話框去承載相應(yīng)的操作。雖然用得多,但是很多人其實(shí)并不知道怎么去寫。饒有興趣,自己嘗試寫了一個(gè)。
API參數(shù) | 說明 | 類型 | 默認(rèn)值 |
---|---|---|---|
afterClose | Modal 完全關(guān)閉后的回調(diào) | function | 無 |
cancelText | 取消按鈕文字 | string | 取消 |
closable | 是否顯示右上角的關(guān)閉按鈕 | boolean | true |
destroyOnClose | 關(guān)閉時(shí)銷毀 Modal | boolean | false |
footer | 底部內(nèi)容,當(dāng)不需要默認(rèn)底部按鈕時(shí),可以設(shè)為 false | boolean | true |
maskClosable | 點(diǎn)擊蒙層是否允許關(guān)閉 | boolean | true |
okText | 確認(rèn)按鈕文字 | string | 確定 |
title | 標(biāo)題 | string|html節(jié)點(diǎn) | 標(biāo)題 |
width | 寬度 | number | 500 |
zIndex | 設(shè)置 Modal 的 z-index | number | 1000 |
keyboard | 是否支持鍵盤esc關(guān)閉 | boolean | true |
onCancel | 點(diǎn)擊遮罩層或右上角叉或取消按鈕的回調(diào) | function(e) | 無 |
onOk | 點(diǎn)擊確定回調(diào) | function(e) | 無 |
參數(shù) | 說明 | 使用形式 |
---|---|---|
set | 已覆蓋默認(rèn)的形式,設(shè)置新的屬性,內(nèi)部 Object.assign(this.options, newOptions) | model.set(newOptions) |
open | 打開對(duì)話框 | model.open() |
close | 關(guān)閉對(duì)話框 | model.close() |
destroy | 與close的區(qū)別在于,會(huì)從節(jié)點(diǎn)上刪除 | model.destroy() |
對(duì)話框全局中使用一個(gè)就夠了,為了防止生成多個(gè)對(duì)話框,我們使用單例構(gòu)造
var Dialog = (function () { var instance; return function (options) { if (!instance) { instance = new Modal(options); } return instance; } })()
這里主要運(yùn)用到了閉包中的特性
modal.js代碼
var Dialog = (function () { var instance; return function (options) { if (!instance) { instance = new Modal(options); } return instance; } })() class Modal { constructor(options) { //默認(rèn)屬性 this.initOptions = { title: "標(biāo)題", 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");//節(jié)點(diǎn)實(shí)例,因?yàn)橹恍枰粋€(gè)模態(tài)框,這里設(shè)置節(jié)點(diǎn)就可以了 this.mounted = false; //是否掛載在節(jié)點(diǎn)上 } //處理模態(tài)框的點(diǎn)擊事件 _modalClick(e) { var className = e.target.className; //匹配類名,例如 帶有 class="modal-close" 的元素點(diǎn)擊可以關(guān)閉模態(tài)框 if (new RegExp("(s|^)modal-close(s|$)").test(className)) { this.cancel(); //關(guān)閉模態(tài)框 } else if (new RegExp("(s|^)modal-onOk(s|$)").test(className)) { this.onOk(); //執(zhí)行確定按鈕的回調(diào) } else if (new RegExp("(s|^)modal-container(s|$)").test(className)) { this.outSideClick(); //模態(tài)框外的點(diǎn)擊 } } //處理鍵盤ESC關(guān)閉 _escClose(e) { var code = e.keyCode; if (code === 27) { this.cancel(); } } //渲染模態(tài)框節(jié)點(diǎn) 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}`; } //蒙層點(diǎn)擊關(guān)閉 outSideClick() { if (this.options.maskClosable) { this.close(); } } //處理監(jiān)聽 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(); } //點(diǎn)擊確定回調(diào) onOk() { this .options .onOkFn(); this.close(); } /****************** 提供的方法 ********************* */ //設(shè)置屬性 set(options) { Object.assign(this.options, options) this.render() } //打開模態(tài)框 open() { var modal = this.instance; //實(shí)例如果沒掛載 if (!this.mounted) { this.mounted = true; this.render(); document.body.appendChild(modal); this.listen() } removeClass(modal, "close"); addClass(modal, "open"); } //關(guān)閉模態(tài)框 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); } } //從節(jié)點(diǎn)上移除模態(tài)框 destroy() { this.instance.removeEventListener("click", this._modalClick);//移除click監(jiān)聽 window.removeEventListener("keyup", this._escClose);//移除keyup監(jiān)聽 document.body.removeChild(this.instance);//移除模態(tài)框節(jié)點(diǎn) 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: "模態(tài)框標(biāo)題", content: "", header: true, footer: true, destroyOnClose: true, onOkFn: function () { alert("提交成功") }, afterClose: function(){ alert("已經(jīng)關(guān)閉") } } var modal = new Dialog(config); var openBtns = document.querySelectorAll(".open"); openBtns.forEach(function (item, index) { item.onclick = function () { var option = { content: "這是第" + (index + 1) + "個(gè)" } modal.set(option) modal.open(); } })
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/95423.html
摘要:總之,選擇單例模式就是為了避免不一致狀態(tài),避免政出多頭。二餓漢式單例餓漢式單例類在類初始化時(shí),已經(jīng)自行實(shí)例化靜態(tài)工廠方法餓漢式在類創(chuàng)建的同時(shí)就已經(jīng)創(chuàng)建好一個(gè)靜態(tài)的對(duì)象供系統(tǒng)使用,以后不再改變,所以天生是線程安全的。 概念: Java中單例模式是一種常見的設(shè)計(jì)模式,單例模式的寫法有好幾種,這里主要介紹兩種:懶漢式單例、餓漢式單例?! 卫J接幸韵绿攸c(diǎn): 1、單例類只能有一個(gè)實(shí)例。 ...
摘要:簡介單例模式是指整個(gè)應(yīng)用中類只有一個(gè)對(duì)象實(shí)例的設(shè)計(jì)模式。它是一種常見的設(shè)計(jì)模式,在計(jì)算機(jī)系統(tǒng)中,線程池緩存日志對(duì)象對(duì)話框打印機(jī)數(shù)據(jù)庫操作顯卡的驅(qū)動(dòng)程序常被設(shè)計(jì)成單例。 簡介 單例模式是指整個(gè)應(yīng)用中類只有一個(gè)對(duì)象實(shí)例的設(shè)計(jì)模式。它通常被用來創(chuàng)建對(duì)象,確保某個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。 它是一種常見的設(shè)計(jì)模式,在計(jì)算機(jī)系統(tǒng)中,線程池、緩存、日志對(duì)象、對(duì)話框、打...
摘要:一單例模式定義單例模式確保某個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。技術(shù)實(shí)現(xiàn)單例模式靜態(tài)內(nèi)部類評(píng)價(jià)使用靜態(tài)內(nèi)部類的方式,只有在使用該實(shí)例的時(shí)候,才去加載靜態(tài)內(nèi)部類,從而實(shí)現(xiàn)延時(shí)加載。 一、單例模式定義:單例模式確保某個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。在計(jì)算機(jī)系統(tǒng)中,線程池、緩存、日志對(duì)象、對(duì)話框、打印機(jī)、顯卡的驅(qū)動(dòng)程序?qū)ο蟪1辉O(shè)計(jì)成單例。這些應(yīng)...
摘要:會(huì)一直完善下去,歡迎建議和指導(dǎo),同時(shí)也歡迎中用到了那些設(shè)計(jì)模式中用到了那些設(shè)計(jì)模式這兩個(gè)問題,在面試中比較常見。工廠設(shè)計(jì)模式使用工廠模式可以通過或創(chuàng)建對(duì)象。 我自己總結(jié)的Java學(xué)習(xí)的系統(tǒng)知識(shí)點(diǎn)以及面試問題,已經(jīng)開源,目前已經(jīng) 41k+ Star。會(huì)一直完善下去,歡迎建議和指導(dǎo),同時(shí)也歡迎Star: https://github.com/Snailclimb... JDK 中用到了那...
摘要:總結(jié)我們主要介紹到了以下幾種方式實(shí)現(xiàn)單例模式餓漢方式線程安全懶漢式非線程安全和關(guān)鍵字線程安全版本懶漢式雙重檢查加鎖版本枚舉方式參考設(shè)計(jì)模式中文版第二版設(shè)計(jì)模式深入理解單例模式我是一個(gè)以架構(gòu)師為年之內(nèi)目標(biāo)的小小白。 初遇設(shè)計(jì)模式在上個(gè)寒假,當(dāng)時(shí)把每個(gè)設(shè)計(jì)模式過了一遍,對(duì)設(shè)計(jì)模式有了一個(gè)最初級(jí)的了解。這個(gè)學(xué)期借了幾本設(shè)計(jì)模式的書籍看,聽了老師的設(shè)計(jì)模式課,對(duì)設(shè)計(jì)模式算是有個(gè)更進(jìn)一步的認(rèn)識(shí)。...
閱讀 1726·2021-11-19 09:40
閱讀 2968·2021-09-24 10:27
閱讀 3253·2021-09-02 15:15
閱讀 1919·2019-08-30 15:54
閱讀 1237·2019-08-30 15:54
閱讀 1402·2019-08-30 13:12
閱讀 667·2019-08-28 18:05
閱讀 2836·2019-08-27 10:53