原生js封裝彈出層

我們平常在項(xiàng)目中磷蜀,通常需要給用戶操作的結(jié)果進(jìn)行提示褐隆,但是js默認(rèn)給出的提示彈窗樣式又比較丑庶弃,所以我們可以自己封裝彈出層歇攻,用來(lái)給用戶做不同的提示葬毫,具體效果如下:
普通彈窗如下圖:


普通彈窗

詢問(wèn)彈窗如下圖:


詢問(wèn)彈窗

提示彈窗如下圖:
提示彈窗

加載彈窗如下圖:
加載彈窗

封裝的代碼,使用單例模式進(jìn)行封裝烂斋,代碼如下:

let popup = Popup = (function(){
    class Popup {
        // 構(gòu)造函數(shù)中定義公共要使用的div
        constructor() {
            // 定義所有彈窗都需要使用的遮罩
            this.mask = document.createElement('div')
            // 設(shè)置樣式
            this.setStyle(this.mask, {
                width: '100%',
                height: '100%',
                backgroundColor: 'rgba(0, 0, 0, .2)',
                position: 'absolute',
                left: 0,
                top: 0
            })
            // 創(chuàng)建中間顯示內(nèi)容的水平并垂直居中的div
            this.content = document.createElement('div')
            // 設(shè)置樣式
            this.setStyle(this.content, {
                width: '300px',
                height: '150px',
                backgroundColor: '#fff',
                boxShadow: '0 0 2px #999',
                position: 'absolute',
                left: '50%',
                top: '50%',
                transform: 'translate(-50%,-50%)',
                borderRadius: '3px'
            })
            // 將這個(gè)小div放在遮罩中
            this.mask.appendChild(this.content)
        }
        // 中間有彈框的 - 適用于alert和confirm
        middleBox(param) {
            // 先清空中間小div的內(nèi)容 - 防止調(diào)用多次煎源,出現(xiàn)混亂
            this.content.innerHTML = ''
            // 定義標(biāo)題和內(nèi)容變量
            let title = '默認(rèn)標(biāo)題內(nèi)容',content = '彈窗的默認(rèn)提示信息!';
            // 檢測(cè)參數(shù)類型
            if({}.toString.call(param) === '[object String]') {
                content = param
            } else if({}.toString.call(param) === '[object Object]') {
                title = param.title
                content = param.content
            }
            // 將遮罩放在body中顯示
            document.body.appendChild(this.mask)
            // 給中間的小div設(shè)置默認(rèn)的排版
            // 上面標(biāo)題部分
            this.title = document.createElement('div')
            // 設(shè)置樣式
            this.setStyle(this.title, {
                width: '100%',
                height: '50px',
                borderBottom: '1px solid #ccc',
                lineHeight: '50px',
                paddingLeft: '20px',
                boxSizing: 'border-box',
                color: '#666'
            })
            // 設(shè)置默認(rèn)標(biāo)題內(nèi)容
            this.title.innerText = title
            // 將標(biāo)題部分放在中間div中
            this.content.appendChild(this.title)
            // 關(guān)閉按鈕
            this.closeBtn = document.createElement('a')
            // 設(shè)置內(nèi)容
            this.closeBtn.innerText = '×'
            // 設(shè)置href屬性
            this.closeBtn.setAttribute('href', 'javascript:;')
            // 設(shè)置樣式
            this.setStyle(this.closeBtn, {
                textDecoration: 'none',
                color: '#666',
                position: 'absolute',
                right: '10px',
                top: '6px',
                fontSize: '25px'
            })
            // 將關(guān)閉按鈕放在中間小div中
            this.content.appendChild(this.closeBtn)
            // 下面具體放內(nèi)容的部分
            this.description = document.createElement('div')
            // 放入默認(rèn)內(nèi)容
            this.description.innerText = content
            // 將默認(rèn)內(nèi)容放在中間的小div中
            this.content.appendChild(this.description)
            // 設(shè)置樣式
            this.setStyle(this.description, {
                color: '#666',
                paddingLeft: '20px',
                lineHeight: '50px'
            })
        }
        // 彈出提示框
        alert(param) {
            this.middleBox(param)
            // 右下角的確定按鈕
            this.btn = document.createElement('button')
            // 添加內(nèi)容
            this.btn.innerText = '確定'
            // 設(shè)置內(nèi)容
            this.setStyle(this.btn, {
                backgroundColor: 'rgb(30, 159, 255)',
                position: 'absolute',
                right: '10px',
                bottom: '5px',
                outline: 'none',
                border: 'none',
                color: '#fff',
                fontSize: '16px',
                borderRadius: '2px',
                padding: '0 10px',
                height: '30px',
                lineHeight: '30px'
            })
            // 將按鈕放在div中
            this.content.appendChild(this.btn)
            // 關(guān)閉按鈕和確定按鈕的點(diǎn)擊事件
            this.btn.onclick = this.closeBtn.onclick = () => this.close()
        }
        confirm(info, obj, cb1, cb2) {
            // 調(diào)用創(chuàng)建中間小div的函數(shù)
            this.middleBox(info)
            // 設(shè)置默認(rèn)參數(shù)
            let defaultBtn = { // 默認(rèn)按鈕
                btn: ['確定', '取消']
            }
            // 設(shè)置默認(rèn)的確定按鈕和取消按鈕點(diǎn)擊后要執(zhí)行的函數(shù)
            let affirm = function(){}
            let cancel = function(){}
            // 替換默認(rèn)參數(shù) 
            if(obj && {}.toString.call(obj) === '[object Object]') {
                for(let attr in obj) {
                    defaultBtn[attr] = obj[attr]
                }
            }       
            if(cb1 && {}.toString.call(cb1) === '[object Function]') {
                affirm = cb1
            }
            if(cb2 && {}.toString.call(cb2) === '[object Function]') {
                cancel = cb2
            }
            // 創(chuàng)建確定按鈕
            this.btn = document.createElement('button')
            // 添加內(nèi)容
            this.btn.innerText = defaultBtn.btn[0]
            // 設(shè)置內(nèi)容
            this.setStyle(this.btn, {
                backgroundColor: 'rgb(30, 159, 255)',
                position: 'absolute',
                right: '70px',
                bottom: '5px',
                outline: 'none',
                border: 'none',
                color: '#fff',
                fontSize: '16px',
                borderRadius: '2px',
                padding: '0 10px',
                height: '30px',
                lineHeight: '30px'
            })
            // 將按鈕放在div中
            this.content.appendChild(this.btn)
            // 創(chuàng)建取消按鈕
            this.cancel = document.createElement('button')
            // 添加內(nèi)容
            this.cancel.innerText = defaultBtn.btn[1]
            // 設(shè)置內(nèi)容
            this.setStyle(this.cancel, {
                backgroundColor: 'transparent',
                position: 'absolute',
                right: '10px',
                bottom: '5px',
                outline: 'none',
                border: '1px solid #ccc',
                color: '#666',
                fontSize: '16px',
                borderRadius: '2px',
                padding: '0 10px',
                height: '30px',
                lineHeight: '30px'
            })
            // 將按鈕放在div中
            this.content.appendChild(this.cancel)
            // 關(guān)閉按鈕的點(diǎn)擊事件
            this.closeBtn.onclick = () => this.close()
            // 確定按鈕的點(diǎn)擊事件
            this.btn.onclick = () => {
                affirm()
                this.close()
            }
            // 取消按鈕的點(diǎn)擊事件
            this.cancel.onclick = () => {
                cancel()
                this.close()
            }
        }
        msg(str, param) {
            // 清空中間的小div中的內(nèi)容
            this.content.innerHTML = ''
            // 定義默認(rèn)參數(shù)
            let content = '默認(rèn)提示內(nèi)容'
            let options = {
                time: 2000,
            }
            // 將參數(shù)覆蓋掉默認(rèn)值
            if(str && {}.toString.call(str) === '[object String]') {
                content = str
            }
            if(param && {}.toString.call(param) === '[object Object]') {
                for(let attr in param) {
                    options[attr] = param[attr]
                }
            }
            // 將遮罩放在body中顯示
            document.body.appendChild(this.mask)
            // 給遮罩中間的div設(shè)置樣式
            this.setStyle(this.content, {
                width: 'auto',
                height: '80px',
                backgroundColor: 'rgb(255, 255, 255)',
                boxShadow: '0 0 2px #999',
                position: 'absolute',
                left: '50%',
                top: '50%',
                transform: 'translate(-50%,-50%)',
                borderRadius: '3px',
                padding: '0 30px 0',
                lineHeight: '80px',
                color: '#666'
            })
            // 定義icon所用的標(biāo)簽
            let icon = document.createElement('span')
            // 判斷icon
            if(options.icon === 1) {
                // 給icon設(shè)置內(nèi)容和樣式
                icon.innerText = '√'
                this.setStyle(icon, {
                    width: '30px',
                    height: '30px',
                    border: '3px solid rgb(56, 201, 177)',
                    borderRadius: '50%',
                    display: 'inline-block',
                    color: 'rgb(56, 201, 177)',
                    lineHeight: '30px',
                    textAlign: 'center',
                    margin: '0 10px',
                    fontSize: '20px',
                    fontWeight: 'bold'
                })
            } else if(options.icon === 0) {
                // 給icon設(shè)置內(nèi)容和樣式
                icon.innerText = '×'
                this.setStyle(icon, {
                    width: '30px',
                    height: '30px',
                    border: '3px solid rgb(233, 91, 76)',
                    borderRadius: '50%',
                    display: 'inline-block',
                    color: 'rgb(233, 91, 76)',
                    lineHeight: '30px',
                    textAlign: 'center',
                    margin: '0 10px',
                    fontSize: '20px',
                    fontWeight: 'bold'
                })
            } else {
                this.setStyle(this.content, {
                    width: 'auto',
                    height: '50px',
                    backgroundColor: 'rgba(0, 0, 0, 0.5)',
                    boxShadow: '0 0 2px #999',
                    position: 'absolute',
                    left: '50%',
                    top: '50%',
                    transform: 'translate(-50%, -50%)',
                    borderRadius: '3px',
                    padding: '0 30px 0',
                    lineHeight: '50px',
                    color: '#fff'
                })
            }
            // 將icon放到小div中
            this.content.appendChild(icon)
            // 給中間小div放入內(nèi)容
            this.content.innerHTML += content
            // 延遲一會(huì)自動(dòng)消失
            setTimeout(() => {
                // 從body中將遮罩刪除
                if(this.mask.parentElement) {
                    document.body.removeChild(this.mask)
                }
            }, options.time)
        }
        load() {
            // 將遮罩放到body中顯示
            document.body.appendChild(this.mask)
            // 給中間的小div設(shè)置樣式
            this.setStyle(this.content, {
                border: 'none',
                boxShadow: '0 0 0 transparent',
                backgroundColor: 'transparent'
            })
            // 創(chuàng)建旋轉(zhuǎn)的div
            for(let i = 0; i < 8; i++) {
                let div = document.createElement('div')
                this.setStyle(div, {
                    width: '4px',
                    height: '12px',
                    backgroundColor: 'rgb(6, 43, 78)',
                    transformOrigin: '0 15px',
                    transform: 'rotate('+360/8*i+'deg) translate(-50%, -50%)',
                    position: 'absolute',
                    left: '50%',
                    top: '50%',
                    opacity: '0.5'
                })
                if(i === 0) {
                    div.style.opacity = 1
                }
                this.content.appendChild(div)
            }
            // 讓div循環(huán)增加透明度
            let i = 0
            return setInterval(() => {
                i++
                if(i === this.content.children.length) {
                    i = 0
                    this.content.children[this.content.children.length-1].style.opacity = '0.5'
                }else{
                    this.content.children[i-1].style.opacity = '0.5'
                }
                
                this.content.children[i].style.opacity = 1
            }, 50)
        }
        close(timerId) {
            // 如果有定時(shí)器柄错,就停止定時(shí)器
            if(timerId) clearInterval(timerId)
            // 將遮罩從body中刪除
            document.body.removeChild(this.mask)
        }
        // 設(shè)置樣式的函數(shù)
        setStyle(ele, styleObj) {
            for(let attr in styleObj){
                ele.style[attr] = styleObj[attr]
            }
        }
    }
    let popup = null;
    return (function() {
        if(!popup) {
            popup = new Popup()
        }
        return popup;
    })()
})()

調(diào)用方式和使用說(shuō)明如下:

  • 普通彈窗

    // 默認(rèn)字符串表示彈窗中提示的內(nèi)容
    popup.alert('操作成功')
    popup.alert({
        // title表示彈窗中的標(biāo)題
        title: '標(biāo)題', 
        // content表示彈窗中提示的內(nèi)容
        content: '操作成功'
    })
    
  • 詢問(wèn)彈窗

    // 默認(rèn)字符串表示詢問(wèn)彈窗中的內(nèi)容
    popup.confirm('操作成功')
    popup.confirm({
        // title表示詢問(wèn)彈窗的標(biāo)題
        title: '標(biāo)題', 
        // content表示詢問(wèn)彈窗的內(nèi)容
        content: '操作成功'
    },{
        // btn表示给猾,兩個(gè)按鈕分別顯示的內(nèi)容
        btn: ['ok' ,'no']
    },function(){
        // 第一個(gè)函數(shù)敢伸,表示點(diǎn)擊了ok按鈕要執(zhí)行的代碼
        alert('ok')
    },function(){
        // 第二個(gè)函數(shù),表示點(diǎn)擊了no按鈕要執(zhí)行的代碼
        alert('no')
    })
    
  • 提示彈窗

    popup.msg('提示的內(nèi)容')
    popup.msg('提示的內(nèi)容',{
        // icon:0表示失敗恒削,1表示成功
        icon: 0
    })
    popup.msg('提示的內(nèi)容',{
        icon: 1,
        // time表示自動(dòng)在多少毫秒之后消失
        time: 5000
    })
    
  • 加載彈窗

    var i = popup.load()
    

    要關(guān)閉的時(shí)候池颈,使用:

    popup.close(i)
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末尾序,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子躯砰,更是在濱河造成了極大的恐慌蹲诀,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弃揽,死亡現(xiàn)場(chǎng)離奇詭異脯爪,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)矿微,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門涌矢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)塔次,“玉大人,你說(shuō)我怎么就攤上這事继榆】稼澹” “怎么了秽之?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵董虱,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我溃槐,道長(zhǎng)对人,這世上最難降的妖魔是什么姻几? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任络拌,我火速辦了婚禮馅而,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘屯蹦。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般凌盯。 火紅的嫁衣襯著肌膚如雪春霍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天喧伞,我揣著相機(jī)與錄音,去河邊找鬼挖函。 笑死振定,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的丧肴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼眶痰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼竖伯!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吗伤,失蹤者是張志新(化名)和其女友劉穎夕冲,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疼进,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片主经。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖透绩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤厂汗,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布祈争,位于F島的核電站沮峡,受9級(jí)特大地震影響呼畸,放射性物質(zhì)發(fā)生泄漏瞬痘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧可岂,春花似錦峰锁、人聲如沸魄衅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至瘸彤,卻和暖如春中贝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留策幼,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓本股,卻偏偏與公主長(zhǎng)得像棘街,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容