我們平常在項(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)