搜索
您的当前位置:首页正文

JS实现自定义弹窗功能

2020-11-27 来源:抵帆知识网

众所周知,浏览器自带的原生弹窗很不美观,而且功能比较单一,绝大部分时候我们都会按照设计图自定义弹窗或者直接使用注入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" rel="external nofollow" >
</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;
 }

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以及css或者直接把相关代码加到自己的公共js中即可直接调用,注意,构造函数调用要用new.

总结

以上所述是小编给大家介绍的JS实现自定义弹窗功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

Top