众所周知,浏览器自带的原生弹窗很不美观,而且功能比较单一,绝大部分时候我们都会按照设计图自定义弹窗或者直接使用注入layer的弹窗等等。前段时间在慕课网上看到了一个自定义弹窗的实现,自己顺便就学习尝试写了下,下面是主要的实现代码并添加了比较详细的注释,分享出来供大家参考。(代码用了ES6部分写法如需兼容低版本浏览器请把相关代码转成es5写法,后面有时间更新为一个兼容性较好的es5版本)

HTML部分:(没什么内容 放置一个按钮调用函数,js中调用实例即可供参考)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>自定义弹窗</title>
<link rel="stylesheet" href="alert.css">
</head>
<body> <button>Click me</button>
<script src="index.js"></script>
<script>
document.querySelector("button").addEventListener("click",()=>{
new $Msg({
content:"我的自定义弹窗好了",
type:"success",
cancle:function(){
let cancle = new $Msg({
content:"我是取消后的回调"
})
},
confirm:function(){
new $Msg({content:"我是确定后的回调"})
}
})
}) </script>
</body>
</html>

样式部分:也放出来供参考,样式可以根据自己的设计图自行更改即可

/* 弹出框最外层 */
.msg__wrap {
position: fixed;
top: 50%;
left: 50%;
z-index: 10;
transition: all .3s;
transform: translate(-50%, -50%) scale(0, 0);
max-width: 50%; background: #fff;
box-shadow: 0 0 10px #eee;
font-size: 10px;
} /* 弹出框头部 */
.msg__wrap .msg-header {
padding: 10px 10px 0 10px;
font-size: 1.8em;
} .msg__wrap .msg-header .msg-header-close-button {
float: right;
cursor: pointer;
} /* 弹出框中部 */
.msg__wrap .msg-body {
padding: 10px 10px 10px 10px;
display: flex;
} /* 图标 */
.msg__wrap .msg-body .msg-body-icon{
width: 80px;
} .msg__wrap .msg-body .msg-body-icon div{
width: 45px;
height: 45px;
margin: 0 auto;
line-height: 45px;
color: #fff;
border-radius: 50% 50%;
font-size: 2em;
} .msg__wrap .msg-body .msg-body-icon .msg-body-icon-success{
background: #32a323;
text-align: center;
} .msg__wrap .msg-body .msg-body-icon .msg-body-icon-success::after{
content: "成";
} .msg__wrap .msg-body .msg-body-icon .msg-body-icon-wrong{
background: #ff8080;
text-align: center;
} .msg__wrap .msg-body .msg-body-icon .msg-body-icon-wrong::after{
content: "误";
} .msg__wrap .msg-body .msg-body-icon .msg-body-icon-info{
background: #80b7ff;
text-align: center;
} .msg__wrap .msg-body .msg-body-icon .msg-body-icon-info::after{
content: "注";
} /* 内容 */
.msg__wrap .msg-body .msg-body-content{
min-width: 200px;
font-size: 1.5em;
word-break: break-all;
display: flex;
align-items: center;
padding-left: 10px;
box-sizing: border-box;
} /* 弹出框底部 */
.msg__wrap .msg-footer {
padding: 0 10px 10px 10px;
display: flex;
flex-direction: row-reverse;
} .msg__wrap .msg-footer .msg-footer-btn {
width: 50px;
height: 30px;
border: 0 none;
color: #fff;
outline: none;
font-size: 1em;
border-radius: 2px;
margin-left: 5px;
cursor: pointer;
} .msg__wrap .msg-footer .msg-footer-cancel-button{
background-color: #ff3b3b;
} .msg__wrap .msg-footer .msg-footer-cancel-button:active{
background-color: #ff6f6f;
} .msg__wrap .msg-footer .msg-footer-confirm-button{
background-color: #4896f0;
} .msg__wrap .msg-footer .msg-footer-confirm-button:active{
background-color: #1d5fac;
} /* 遮罩层 */
.msg__overlay {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 5;
background-color: rgba(0, 0, 0, .4);
transition: all .3s;
opacity: 0;
}

CSS

JS部分:下面是最主要的部分,js方法及交互。自己封装自定义组件均可以此为参考,封装自己的组件。

/*
*自定义弹窗
*/
//自执行函数 形成封闭的作用域 避免全局污染
//传入windwo和document对象 相当于将window和document作为了作用域中的局部变量,
//就不需要内部函数沿着作用域链再查找到最顶层的window 提高运行效率。
(function (window, document) {
//定义一个构造函数Msg 作为弹窗实例的构造函数。
let Msg = function (options) {
//执行初始化操作
this._init(options);
} //定义初始化方法 并对方法传递的参数进行初始化
Msg.prototype = {
_init({
content = "", //文本内容
type = "info", //信息类型
useHTML = false, //是否解析html字符串
showIcon = true, //是否展示弹窗图标
confirm = null, //确认后得回调
cancle = null, //取消后得回调
footer = true, //是否显示底部的确认按钮
header = true, //是否显示头部信息及关闭按钮
title = "提示", //弹窗标题
contentStyle = {}, //内容样式
contentFontSize = "1.5em", //内容字体大小
btnName = ["确定", "取消"] //按钮文字内容
}) {
//将传入的值绑定到this上
this.content = content;
this.type = type;
this.useHTML = useHTML;
this.showIcon = showIcon;
this.confirm = confirm;
this.cancle = cancle;
this.footer = footer;
this.header = header;
this.title = title;
this.contentStyle = contentStyle;
this.contentFontSize = contentFontSize;
this.btnName = btnName; //执行创建元素方法
this._creatElement();
//显示弹窗及遮罩
this._show({
el: this._el,
overlay: this._overlay
});
//绑定事件处理函数
this._bind({
el: this._el,
overlay: this._overlay
});
}, //创建弹窗元素方法
_creatElement() {
//创建最外层得包裹元素
let wrap = document.createElement("div");
wrap.className = "msg__wrap"; //定义弹窗得两个按钮
const [confirmBtnName, cancelBtnName] = this.btnName; //判断是否显示弹窗标题
const headerHTML = this.header ?
`<div class="msg-header">
<span>${this.title}</span>
<span class="msg-header-close-button">×</span>
</div>` : ""; //判断是否显示图标
const iconHTML = this.showIcon ?
`<div class="msg-body-icon">
<div class="msg-body-icon-${this.type}"></div>
</div>` : ""; //判断是否显示弹窗底部按钮
const footerHTML = this.footer ?
`<div class="msg-footer">
<button class="msg-footer-btn msg-footer-cancel-button">${cancelBtnName}</button>
<button class="msg-footer-btn msg-footer-confirm-button">${confirmBtnName}</button>
</div>` : ""; //拼接完整html
const innerHTML = `${headerHTML}
<div class="msg-body">
${iconHTML}
<div class="msg-body-content"></div>
</div>
${footerHTML}`; //将拼接的html赋值到wrap中
wrap.innerHTML = innerHTML; //把自定义的样式进行合并
const contentStyle = {
fontSize: this.contentFontSize,
...this.contentStyle
} //获取内容所属DOM
let content = wrap.querySelector(".msg-body .msg-body-content");
//将传过来的样式添加到contentDOM
for (const key in contentStyle) {
if (contentStyle.hasOwnProperty(key)) {
content.style[key] = contentStyle[key]; }
} //给弹窗的conntent赋值
if (this.useHTML) {
content.innerHTML = this.content;
} else {
content.innerText = this.content;
} //创建遮罩层
let overlay = document.createElement("div");
overlay.className = "msg__overlay"; //把dom挂载到当前实例上
this._overlay = overlay;
this._el = wrap;
}, //弹窗展现方法
_show({
el,
overlay
}) {
//把弹窗的dom和遮罩插入到页面中
document.body.appendChild(el);
document.body.appendChild(overlay); //将弹窗显示出来 timeout进行异步处理显示动画
setTimeout(() => {
el.style.transform = "translate(-50%,-50%) scale(1,1)";
overlay.style.opacity = "1";
})
}, //关闭弹窗方法
_close({
el,
overlay
}) {
//隐藏dom
el.style.transform = "translate(-50%,-50%) scale(0,0)";
overlay.style.opcity = "0";
//根据动画时间 动画完成再移除
setTimeout(() => { //把弹窗的dom和遮罩移除
document.body.removeChild(el)
document.body.removeChild(overlay);
}, 300);
}, //事件处理函数,为DOM绑定事件
_bind({
el,
overlay
}) {
//保存当前this
//const _this = this; const cancle = (e) => {
this.cancle && this.cancle.call(this, e);
//隐藏弹窗
//hideMsg();
this._close({
el,
overlay
});
}
//确认弹窗
const confirm = (e) => {
this.confirm && this.confirm.call(this, e);
this._close({
el,
overlay
});
} //顶部关闭按钮绑定事件
if (this.header) {
el.querySelector(".msg-header-close-button").addEventListener("click", cancle);
}
//弹窗底部两个按钮事件监听
if (this.footer) {
el.querySelector(".msg-footer-cancel-button").addEventListener("click", cancle);
el.querySelector(".msg-footer-confirm-button").addEventListener("click", confirm)
}
} } //将构造函数暴露到window 可直接在全局作用域中访问构造函数
window.$Msg = Msg; })(window, document);

JS

到此,一个完整的自定义弹窗组件已完成,只需要引入该js以及css或者直接把相关代码加到自己的公共js中即可直接调用,注意,构造函数调用要用new.

下面是点击之后弹窗图效果(gif动态图):

觉得不错的,赶快动手试试吧。纸上得来终觉浅,绝知此事要躬行。

js实现自定义弹窗的更多相关文章

  1. JS调用自定义弹窗【bootstrap】

    function commonConfirm(msg,call){ showConfirmBox("消息提示",msg,call); } $(document).on('click ...

  2. 基于React.js网页版弹窗|react pc端自定义对话框组件RLayer

    基于React.js实现PC桌面端自定义弹窗组件RLayer. 前几天有分享一个Vue网页版弹框组件,今天分享一个最新开发的React PC桌面端自定义对话框组件. RLayer 一款基于react. ...

  3. 自动化测试基础篇--Selenium中JS处理浏览器弹窗

    摘自https://www.cnblogs.com/sanzangTst/p/7692454.html 浏览器弹窗: 现在大多数网站都会使用自定义弹窗,使用Selenium自带的方法暂时处理不了,这时 ...

  4. 支付宝小程序自定义弹窗插件|支付宝dialog插件|model插件

    支付宝小程序自定义弹窗组件wcPop|小程序自定义对话框|actionSheet弹窗模板 支付宝小程序官方提供的alert提示框.dialog对话框.model弹窗功能比较有限,有些都不能随意自定义修 ...

  5. 微信小程序自定义弹窗wcPop插件|仿微信弹窗样式

    微信小程序自定义组件弹窗wcPop|小程序消息提示框|toast自定义模板弹窗 平时在开发小程序的时候,弹窗应用场景还是蛮广泛的,但是微信官方提供的弹窗比较有局限性,不能自定义修改.这个时候首先想到的 ...

  6. react.js插件开发,x-dailog弹窗浮层组件

    react.js插件开发,x-dailog弹窗浮层组件 我认为,每一个组件都应该有他自带的样式和属性事件回调配置.所以我会给x-dialog默认一套简单的样式,和各种默认的配置项.所有react插件示 ...

  7. 基于JQ的自定义弹窗组件

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. svelte组件:Svelte自定义弹窗Popup组件|svelte移动端弹框组件

    基于Svelte3.x自定义多功能svPopup弹出框组件(组件式+函数式) 前几天有分享一个svelte自定义tabbar+navbar组件,今天继续带来svelte自定义弹窗组件. svPopup ...

  9. ExtJs基础知识总结:自定义弹窗和ComboBox自动联想加载(四)

    概述 Extjs弹窗可以分为消息弹窗.对话框,这些弹窗的方式ExtJs自带的Ext.Msg.alert就已经可以满足简单消息提示,但是相对复杂的提示,比如如何将Ext.grid.Panel的控件显示嵌 ...

随机推荐

  1. numpy函数笔记(持续更新)

    numpy函数笔记 np.isin用法 np.isin(a,b) 用于判定a中的元素在b中是否出现过,如果出现过返回True,否则返回False,最终结果为一个形状和a一模一样的数组.(注意:这里的a ...

  2. [LeetCode]603. 连续空余座位(Mysql、自连接)

    题目 几个朋友来到电影院的售票处,准备预约连续空余座位. 你能利用表 cinema ,帮他们写一个查询语句,获取所有空余座位,并将它们按照 seat_id 排序后返回吗? | seat_id | fr ...

  3. [程序员代码面试指南]链表问题-将单链表的每k个节点之间逆序

    题目描述 给定一个单链表的表头节点head,实现一个调整单链表的函数,是的每k个节点之间逆序,如果最后不够k个节点一组,则不调整最后几个节点. 题解 内部函数reverse实现链表beg到end的翻转 ...

  4. JAVA基础知识之面向对象编程知识汇总

    JAVA基础课程部分面向对象已经学习完成,知识结构如下: 总体知识框架: 类的结构: 面向对象编程三大特征: 关键字和抽象类接口等: 常见知识汇总: 成员变量和局部变量比较 有无返回值方法比较: 权限 ...

  5. 217。数据中是否有重复元素(哈希表/set简法)

    给定一个整数数组,判断是否存在重复元素. 如果任意一值在数组中出现至少两次,函数返回 true .如果数组中每个元素都不相同,则返回 false . 示例 1: 输入: [1,2,3,1] 输出: t ...

  6. Java 异常面试题(2020 最新版)

    Java异常架构与异常关键字 Java异常简介 Java异常是Java提供的一种识别及响应错误的一致性机制. Java异常机制可以使程序中异常处理代码和正常业务代码分离,保证程序代码更加优雅,并提高程 ...

  7. archaius(3) 配置管理器

    基于上一节介绍的配置源,我们来继续了解配置管理器.配置源只是抽象了配置的获取来源,配置管理器是基于配置源的基础上对这些配置项进行管理.配置管理器的主要功能是将配置从目标位置加载到内存中,并且管理内存配 ...

  8. 现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?

    Thread t1 = new Thread(new T1()); Thread t2 = new Thread(new T2()); Thread t3 = new Thread(new T3()) ...

  9. vue 项目中实时请求接口 建立长连接

    需求:在项目中需要每隔五秒请求一次接口 第一种方法:直接在mounted钩子函数中处理 mounted() { window.setInterval(() => { setTimeout(thi ...

  10. ApiView 的使用

    1.APIview使用.   https://www.cnblogs.com/xiaonq/p/10124104.html ModelVIewSet 是对 APIView 封装 ModelSerial ...