H5 pc端,移动端自定义弹窗模块思路
再一次项目中要求 在提交时 要让客户核对下信息 并且要去输入密码 然而再用模块时发现没有合适的 安卓的我们可以写 可是没人写ios 最后只有走H5 JS这条路线 因为这个不论是安卓还是ios都可用 当时我就想如果我弄一个模块 以后想用时直接引入文件就行了 不用每次都去写弹窗 那么就模块化 而且这个应该很简单 用不到什么高科技 咱们就用js就能写吧
编写前先想一想 自己需要什么 需要怎么做 首先做什么 然后怎么做 因为我只是个小码农 一个代码的搬运工
第一步: 我需要有个参考 我要做成什么样子 我得有一个静态页面 好的 那就先写个静态的弹窗样式 以下是css 和html
html部分
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" />
<meta name="format-detection" content="telephone=no">
<title></title>
</head>
<body>
<div class="alert_box">
<div class="small_win">
<div class="alert_box_title">
<p class="alert_title_text">title</p>
</div>
<div class="alert_box_content">
<ul class="alert_box_content_ul">
<li>信息1:1</li>
<li>信息2:2</li>
</ul>
<div class="alert_box_input"><input type="text" placeholder="请输入密码" class="alert_input" /></div>
<div class="alert_box_sure">
<button class="alert_box_btn">btn1</button>
<button class="alert_box_btn">btn2</button>
</div>
</div>
</div>
</div>
</body>
</html>
css部分
* {
padding: 0;
margin: 0;
list-style: none;
}
.alert_box {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.5);
}
.alert_box .small_win {
background: #fff;
width: 80%;
position: absolute;
top: 50%;
left: 50%;
padding-bottom: 15px;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
border-radius: 10px;
overflow: hidden;
}
.alert_box .small_win .alert_box_title {
background: #ff0000;
padding: 10px 0;
text-align: center;
font-size: 16px;
}
.alert_box .small_win .alert_box_content {
width: 90%;
margin: 0 auto;
margin-top: 10px;
}
.alert_box .small_win .alert_box_content ul li {
padding: 5px 0;
}
.alert_box_input input {
width: 100%;
border: none;
font-size: 16px;
border-bottom: 1px solid #ddd;
padding: 10px 0;
outline: none;
}
.alert_box_sure {
text-align: center;
margin-top: 15px;
}
.alert_box_sure .alert_box_btn {
border: none;
width: 40%;
padding: 6px;
margin-right: 5px;
outline: none;
}
静态页面完成 pc上看着有点丑 在移动端还可以 这个可以根据自己需求调整
第二步 :看一下都有什么是需要动态写入的然后找对象
1.顶部提示信息也就是(.alert_title_text)这里面的内容
2.需要确认的信息(.alert_box_content_ul)在这里面
3.如果不用输入内容 我们的input就可以不要了 说以input也是可选的
4.按钮的话有时候一个就够了 所以这个也是可选的
5.开始找对象(比说的多了一点 因为后面要用到 一会再解释)
//box
var alertBox = document.getElementsByClassName('alert_box')[0];
var smallWin = document.getElementsByClassName('small_win')[0];
//title
var titleBox = document.getElementsByClassName("alert_box_title")[0];
var title = titleBox.getElementsByClassName("alert_title_text")[0];
//content
var cUl = document.getElementsByClassName("alert_box_content_ul")[0];
//input
var putBox = document.getElementsByClassName("alert_box_input")[0];
var put = putBox.getElementsByClassName("alert_input")[0];
//btn
var btnBox = document.getElementsByClassName("alert_box_sure")[0];
第三步:写一个方法把 需要的数据动态写进去
因为我们需要一些数据来写入(json格式)
var msg = {
title: 提示, //这里是title需要显示的信息
content: [{ // 设置提示内容不传 则不显示 写个数组比较好调用
text: "提示1"
}, {
text: "提示2"
}, {
text: "提示3"
}],
btn: ["确认", "取消"], // 设置button按钮 最多传两个 一样是数组 方便写入
}
现在开始写一个方法并且把数据放进去 因为我们有点事件 所以我们这里需要两个参数 一个是配置的信息 一个是回调函数
pushSmgInit(msg)
function pushSmgInit(msg,fn) {
//title
var titleBox = document.getElementsByClassName("alert_box_title")[0];
var title = titleBox.getElementsByClassName("alert_title_text")[0];
//content
var cUl = document.getElementsByClassName("alert_box_content_ul")[0];
//input
var putBox = document.getElementsByClassName("alert_box_input")[0];
var put = putBox.getElementsByClassName("alert_input")[0];
//btn
var btnBox = document.getElementsByClassName("alert_box_sure")[0];
if(msg.title) { //title这里加一些判断 万一要是不传的话 让他有个默认的
title.innerHTML = msg.title;
} else {
title.innerHTML = "标题";
}
if(msg.content) { //内容这里也加一些判断 如果不传如何显示
var liStr = ""
for(var i in msg.content) {
liStr += '<li><span class="key">' + msg.content[i].text + '</span></li>'
}
cUl.innerHTML = liStr
}
if(!msg.isInput) { //这里获取input是否显示 默认是隐藏的
putBox.style.display = "none"
}
put.setAttribute("type", "type") //设置一下input的type值
if(msg.inputType) { //这里判断一下有没有设置input的type值 type值只能为type和password 如果不传默认为type
if(msg.inputType != "type") {
if(msg.inputType != "password") {
putBox.style.display = "none"
}
}
put.setAttribute("type", msg.inputType)
}
if(msg.inputVal) { //设置input的placeholder 不传则默认为"请输入点什么"
put.setAttribute("placeholder", msg.inputVal)
} else {
put.setAttribute("placeholder", "请输入点什么")
}
if(msg.btn) { //设置按钮信息 不传则不显示按钮
var btnStr = ""
if(msg.btn.length < 1) {
btnStr += '<button class="alert_box_btn">确认</button>'
}
for(var i in msg.btn) {
if(i >= 2) { //这里判断一下如果超过两个参数 则最多显示两个
return
}
btnStr += '<button class="alert_box_btn">' + msg.btn[i] + '</button>'
}
btnBox.innerHTML = btnStr
}
}
到这里 已经差不多了 但是不怎么好看
第四步 美化一下这个弹窗 让我们可以调用时自己修改一下样式 我们可以用js来设置元素的属性 那么我也可以把想要的样式放在 上面的假数据里面 像动态添加数据一样 用js获取并添加样式 下面是修改后的数据
var msg = {
title: { //设置顶部提示信息
bg: '#ff0000', //设置顶部提示信息背景
context: "确认信息", //设置顶部提示信息内容 不传默认提示 "标题"
color: "#fff" //设置顶部提示信息的文字颜色
},
context: [{ // 设置提示内容不传 则不显示 写个数组比较好调用
text: "提示1"
}, {
text: "提示2"
}, {
text: "提示3"
}],
isInput: true, // 设置是否显示input框
inputType: "type", // 设置input框的type值 只能为password或type
inputVal: "请输入点什么", //设置input的value值
btn: ["确认", "取消"], // 设置button按钮 最多传两个
btnLeft: { // 设置左边按钮样式 若按钮只有一个则取这里面的样式
bg: "#ddd", //设置设置左边按钮背景
color: "#000", //设置设置左边按钮文字颜色
fontSize: 16 //设置设置左边按钮字体大小
},
btnRight: { // 设置右边按钮样式 若按钮只有一个则忽略此配置
bg: "#ff0000", //设置设置右边按钮背景
color: "#fff", //设置设置右边按钮背景
fontSize: 16 //设置设置右边按钮字体大小
}
}
下面我们就要在我们上面的方法里添加一些东西 获取样式 并添加进去
function pushSmgInit(msg,fn) { //title
var titleBox = document.getElementsByClassName("alert_box_title")[0];
var title = titleBox.getElementsByClassName("alert_title_text")[0];
//content
var cUl = document.getElementsByClassName("alert_box_content_ul")[0];
//input
var putBox = document.getElementsByClassName("alert_box_input")[0];
var put = putBox.getElementsByClassName("alert_input")[0];
//btn
var btnBox = document.getElementsByClassName("alert_box_sure")[0];
if(msg.title) { //title这里加一些判断 万一要是不传的话 让他有个默认的
if(msg.title.context) {
title.innerHTML = msg.title.context;
} else {
title.innerHTML = "标题";
}
if(msg.title.bg) { //设置背景
titleBox.style.background = msg.title.bg;
}
if(msg.title.color) { //设置颜色
title.style.color = msg.title.color;
}
} else {
title.innerHTML = "标题";
}
if(msg.content) { //内容这里也加一些判断 如果不传如何显示
var liStr = ""
for(var i in msg.content) {
liStr += '<li><span class="key">' + msg.content[i].text + '</span></li>'
}
cUl.innerHTML = liStr
}
if(!msg.isInput) { //这里获取input是否显示 默认是隐藏的
putBox.style.display = "none"
}
put.setAttribute("type", "type") //设置一下input的type值
if(msg.inputType) { //这里判断一下有没有设置input的type值 type值只能为type和password 如果不传默认为type
if(msg.inputType != "type") {
if(msg.inputType != "password") {
putBox.style.display = "none"
}
}
put.setAttribute("type", msg.inputType)
}
if(msg.inputVal) { //设置input的placeholder 不传则默认为"请输入点什么"
put.setAttribute("placeholder", msg.inputVal)
} else {
put.setAttribute("placeholder", "请输入点什么")
}
if(msg.btn) { //设置按钮信息 不传则不显示按钮
var btnStr = ""
if(msg.btn.length < 1) {
btnStr += '<button class="alert_box_btn">确认</button>'
}
for(var i in msg.btn) {
if(i >= 2) { //这里判断一下如果超过两个参数 则最多显示两个
return
}
btnStr += '<button class="alert_box_btn">' + msg.btn[i] + '</button>'
}
btnBox.innerHTML = btnStr
}
var alertBtn = document.getElementsByClassName("alert_box_btn") //找到所有的btn
if(msg.btn.length >= 1 && msg.btnLeft) { //判断有几个按钮 应该获取哪个配置 不多解释
var btnL = alertBtn[0]
btnL.setAttribute("style", "background:" + msg.btnLeft.bg + ";color:" + msg.btnLeft.color + ";font-size:" + msg.btnLeft.fontSize + "px")
}
if(msg.btn.length >= 2 && msg.btnRight) {
var btnR = alertBtn[1];
btnR.setAttribute("style", "background:" + msg.btnRight.bg + ";color:" + msg.btnRight.color + ";font-size:" + msg.btnRight.fontSize + "px")
}
}
好了现在应该能看到效果了 当然我们还可配置更多属性比如 弹窗的圆角 内容的行高等等 因为就是个思路 就不写这么多了
第五步 下面我们就该点击按钮了
for(var a = 0; a < alertBtn.length; a++) { //这里就是点击按钮 我们要判断点击的是哪个按钮
alertBtn[a].index = a
alertBtn[a].onclick = function() {
var data = {}
if(putBox.style.display === 'none') { //这里判断一下 是否存在输入框 如果不存在我们就把所点击按钮的下标传递出去
fn && fn({
eventType: this.index
})
return
}
fn && fn({ //输入框如果存在 就弹出输入框的的内容 和当前按钮的下标
eventType: this.index,
msg: put.value
})
}
}
第六步 这是一个弹窗 所以就需要关闭 关闭方式有很多 这里就写两个 第一关闭周围的遮罩层 第二 点击按钮
我们先说点遮罩层 这个可选项 我们可以在上面json数据里面配置一下 把下面这个放到配置文件里面就好了
tapClose: true // (可选项)是否点击遮罩层关闭该对话框 默认为false
关闭的话 我们来写个方法
function closeAlert(el) { //这里传递一个参数 方便扩展
if(el) {
al = el
} else {
al = newNode
}
alertBox.style.display=“none”
}
下面就是点击遮罩层关闭弹窗了 这里要注意事件冒泡
if(info.tapClose) { //读取配置文件 判断点击遮罩层是否关闭
alertBox.onclick = function() {
closeAlert()
}
}
smallWin.onclick = function(event) { //阻止事件冒泡
cancelBubble(event)
}
//阻止事件冒泡的方法
function cancelBubble(e) {
var evt = e ? e : window.event;
if(evt.stopPropagation) {
//W3C
evt.stopPropagation();
} else {
//IE
evt.cancelBubble = true;
}
}
点击按钮关闭弹窗就是调用这个模块时的事了 只要调用closeAlert(el) 这方法就好了
做到这里基本上就成型了 因为是做个模块 所以就不希望我们再去写html 我们直接用js动态添加html到页面里面 这样就不用在调用时在写很多html标签了
var newNode = document.createElement("div"); //这里设置一个全局变量 因为要用到
function addlast() {
newNode.innerHTML = '<div class="alert_box"><div class="small_win"><div class="alert_box_title"><p class="alert_title_text"></p></div><div class="alert_box_content"><ul class="alert_box_content_ul"></ul><div class="alert_box_input"><input type="text" placeholder="请输入密码" class="alert_input" /></div><div class="alert_box_sure"></div></div></div></div>'
document.body.appendChild(newNode) //上面是动态创建的文件 这里添加进去 pushSmgInit()这个方法里面调用就行
}
当我在使用时发现有问题 当关闭再打开时里面的数据不对了 后来发现我们关闭时 只是让他隐藏了 上次的属性还在 第二次添加就不好使了 所以我们要改一下关闭的方法 我们直接移除他
function closeAlert (el) {
if(el) {
al = el
} else {
al = newNode
}
document.body.removeChild(newNode)
}
ok 现在就可以了 我们来把它封装一下 当然我改了一些命名 把下面这些代码粘贴复制一下就可以用 也可以和上面对照一下 自己去修改 开始已经说明了 我说的是一个思路 以下就是完整代码了
js部分(封装后的)创建一个名为alertBox.js的文件
(function(window) {
var u = {}
u.alertBox = function(info, fn) {
u.addlast()
//box
var alertBox = document.getElementsByClassName('alert_box')[0];
var smallWin = document.getElementsByClassName('small_win')[0];
//title
var titleBox = document.getElementsByClassName("alert_box_title")[0];
var title = titleBox.getElementsByClassName("alert_title_text")[0];
//content
var cUl = document.getElementsByClassName("alert_box_content_ul")[0];
//input
var putBox = document.getElementsByClassName("alert_box_input")[0];
var put = putBox.getElementsByClassName("alert_input")[0];
//btn
var btnBox = document.getElementsByClassName("alert_box_sure")[0];
if(info.title) {
titleBox.style.background = info.title.bg;
title.innerHTML = info.title.context;
title.style.color = info.title.color;
} else {
title.innerHTML = "标题";
}
if(info.context) {
var liStr = ""
for(var i in info.context) {
liStr += '<li><span class="key">' + info.context[i].text + '</span></li>'
}
cUl.innerHTML = liStr
}
if(!info.isInput) {
putBox.style.display = "none"
}
put.setAttribute("type", "type")
if(info.inputType) {
if(info.inputType != "type") {
if(info.inputType != "password") {
putBox.style.display = "none"
}
}
put.setAttribute("type", info.inputType)
}
if(info.btn) {
var btnStr = ""
if(info.btn.length < 1) {
btnStr += '<button class="alert_box_btn">确认</button>'
}
for(var i in info.btn) {
if(i >= 2) {
return
}
btnStr += '<button class="alert_box_btn">' + info.btn[i] + '</button>'
}
btnBox.innerHTML = btnStr
}
var alertBtn = document.getElementsByClassName("alert_box_btn")
if(info.btn.length >= 1 && info.btnLeft) {
var btnL = alertBtn[0]
btnL.setAttribute("style", "background:" + info.btnLeft.bg + ";color:" + info.btnLeft.color + ";font-size:" + info.btnLeft.fontSize + "px")
}
if(info.btn.length >= 2 && info.btnRight) {
var btnR = alertBtn[1];
btnR.setAttribute("style", "background:" + info.btnRight.bg + ";color:" + info.btnRight.color + ";font-size:" + info.btnRight.fontSize + "px")
}
for(var a = 0; a < alertBtn.length; a++) {
alertBtn[a].index = a
alertBtn[a].onclick = function() {
var data = {}
if(putBox.style.display === 'none') {
fn && fn({
eventType: this.index
})
return
}
fn && fn({
eventType: this.index,
msg: put.value
})
}
}
if(info.tapClose) {
alertBox.onclick = function() {
u.closeAlert(this)
}
}
smallWin.onclick = function(event) {
cancelBubble(event)
}
}
//关闭弹窗
u.closeAlert = function(el) {
if(el) {
al = el
} else {
al = newNode
}
document.body.removeChild(newNode)
}
//阻止事件冒泡
function cancelBubble(e) {
var evt = e ? e : window.event;
if(evt.stopPropagation) {
//W3C
evt.stopPropagation();
} else {
//IE
evt.cancelBubble = true;
}
}
var newNode = document.createElement("div");
u.addlast = function() {
newNode.innerHTML = '<div class="alert_box"><div class="small_win"><div class="alert_box_title"><p class="alert_title_text"></p></div><div class="alert_box_content"><ul class="alert_box_content_ul"></ul><div class="alert_box_input"><input type="text" placeholder="请输入密码" class="alert_input" /></div><div class="alert_box_sure"></div></div></div></div>'
document.body.appendChild(newNode)
}
window.$alert = u;
})(window);
css文件(和上面的没有什么变化)创建一个名为alertBox.css的文件
* {
padding: 0;
margin: 0;
list-style: none;
}
.alert_box {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.5);
}
.alert_box .small_win {
background: #fff;
width: 80%;
position: absolute;
top: 50%;
left: 50%;
padding-bottom: 15px;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
border-radius: 10px;
overflow: hidden;
}
.alert_box .small_win .alert_box_title {
background: #fff;
padding: 10px 0;
text-align: center;
font-size: 16px;
}
.alert_box .small_win .alert_box_content {
width: 90%;
margin: 0 auto;
margin-top: 10px;
}
.alert_box .small_win .alert_box_content ul li {
padding: 5px 0;
}
.alert_box_input input {
width: 100%;
border: none;
font-size: 16px;
border-bottom: 1px solid #ddd;
padding: 10px 0;
outline: none;
}
.alert_box_sure {
text-align: center;
margin-top: 15px;
}
.alert_box_sure .alert_box_btn {
border: none;
width: 40%;
padding: 6px;
margin-right: 5px;
outline: none;
}
html文件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" />
<meta name="format-detection" content="telephone=no">
<title></title>
<link rel="stylesheet" type="text/css" href="alertBox.css" /><!--css写在这里面-->
<style type="text/css">
.click{
width: 80px;
height: 50px;
margin: 40px auto;
background: red;
line-height: 50px;
text-align: center;
}
</style>
</head>
<body>
<div class="click">点击我</div>
</body>
<script type="text/javascript" src="alertBox.js"></script><!--封装好的js写在这里面-->
<script type="text/javascript">
document.getElementsByClassName("click")[0].onclick = function() {
//代码调用示范
$alert.alertBox({ //调用方法
title: { //设置顶部提示信息
bg: '#ff0000', //设置顶部提示信息背景
context: "确认信息", //设置顶部提示信息内容 不传默认提示 "标题"
color: "#fff" //设置顶部提示信息的文字颜色
},
context: [{ // 设置提示内容不传 则不显示
text: "提示的内容1:"
}, {
text: '提示的内容2'
}, {
text: '提示的内容3'
}],
isInput: true, // 设置是否显示input框
inputType: "type", // 设置input框的type值 只能为password或type
btn: ["确认", "取消"], // 设置button按钮 最多传两个
btnLeft: { // 设置左边按钮样式 若按钮只有一个则取这里面的样式
bg: "#ddd", //设置设置左边按钮背景
color: "#000", //设置设置左边按钮文字颜色
fontSize: 16 //设置设置左边按钮字体大小
},
btnRight: { // 设置右边按钮样式 若按钮只有一个则忽略此配置
bg: "#ff0000", //设置设置右边按钮背景
color: "#fff", //设置设置右边按钮背景
fontSize: 16 //设置设置右边按钮字体大小
},
tapClose: true // (可选项)是否点击遮罩层关闭该对话框 默认为false
}, function(ret) {
console.log(ret) //回调函数 如果isInput为false 则返回{eventType: 1} 如果isInput为true 则返回{eventType: 1, msg: ""}
if(ret.eventType == 1) {
$alert.closeAlert()
}
})
}
</script>
</html>
说明下 这个我是用在移动端的 所以在pc上有点丑 不过用的时候可以自己调节以下 希望对大家有所帮助