ES6实现小案例--自定义弹框

按照国际惯例先放效果图

index.html

<!DOCTYPE html>
<html lang="en">

<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>demo</title>
  <link rel="stylesheet" href="./msg.css">
  <style>
    #pop {
      border: 0 none;
      color: #fff;
      outline: none;
      padding: 10px 20px;
      font-size: 18px;
      background: #2594f0;
      cursor: pointer;
    }

    #pop:active {
      background: blue;
    }
  </style>
</head>

<body>
  <button id="pop">弹个框</button>

<!--   <div class="msg__wrap">
    <div class="msg-header">
      <span>确认删除</span>
      <span class="msg-header-close-button">×</span>
    </div>
    <div class="msg-body">
      <div class="msg-body-icon">
        <div class="msg-body-icon-wrong"></div>
      </div>
      <div class="msg-body-content">是否删除</div>
    </div>
    <div class="msg-footer">
      <button class="msg-footer-btn msg-footer-cancel-button">算了吧</button>
      <button class="msg-footer-btn msg-footer-confirm-button">好的</button>
    </div>
  </div> -->
 
  <script src="./msg.js"></script>
  <script type="text/javascript">
    document.querySelector('#pop').addEventListener('click', function() {
      new $Msg({
        content: '贤者模式马上就过去了...真的要清空吗?<span style="color: orange;">~~~</span>',
        confirm:function(e){
          console.log("confirm");
          console.log(this);
        },
         cancel:function(e){
          console.log("cancel");
          console.log(this);
        },
        contentStyle:{
          fontSize:"20px",
          background:"lightgreen"
        },
        useHTML:true
      });
    });
  </script>
</body>

</html>

msg.css

/* 弹出框最外层 */
.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;
}

msg.js

//放入自执行的匿名函数,避免污染全局作用域
//将window和document作为参数传入,可以直接在内部获取,不用再去外部找,性能更优
(function(window,document){
    //构造函数
    let Msg=function(options){
        //初始化一个弹出框
        this._init(options);
    }

    //初始化一个弹出框
    Msg.prototype._init=function({content="",confirm=null,cancel=null,useHTML=false,contentStyle={},contentFontSize="1.5em"}){
        this.content=content;
        this.confirm=confirm;
        this.cancel=cancel;
        this.useHTML=useHTML;
        this.contentStyle=contentStyle;
        this.contentFontSize=contentFontSize;

        //生成DOM元素
        this._createElement();
        //绑定事件
        this._bind([this._el,this._overlay]);
        //显示
        this._show([this._el,this._overlay]);
    }

    //生成DOM元素
    Msg.prototype._createElement=function(){
        let wrap=document.createElement("div");
        wrap.className="msg__wrap";
        //换行前加上转义
        wrap.innerHTML='<div class="msg-header">
                          <span>确认删除</span>
                          <span class="msg-header-close-button">×</span>
                        </div>
                        <div class="msg-body">
                          <div class="msg-body-icon">
                            <div class="msg-body-icon-info"></div>
                          </div>
                          <div class="msg-body-content"></div>
                        </div>
                        <div class="msg-footer">
                          <button class="msg-footer-btn msg-footer-cancel-button">算了吧</button>
                          <button class="msg-footer-btn msg-footer-confirm-button">好的</button>
                        </div>';

        //根据传入的参数控制content样式
        let contentDom=wrap.querySelector(".msg-body .msg-body-content");
        //用解构赋值来合并对象
        const contentStyle={
            contentFontSize:this.contentFontSize,
            ...this.contentStyle
        }
        for(let i in contentStyle){
            //如果是自身的属性
            if(contentStyle.hasOwnProperty(i)){
                //style[i]==>style.i
                //i是属性名,contentStyle[i]是属性值
                contentDom.style[i]=contentStyle[i];
            }
        }
        //如果使用html
        if(this.useHTML){
            contentDom.innerHTML=this.content;
        }else{
            contentDom.innerText=this.content;
        }

        let overlay=document.createElement("div");
        overlay.className="msg__overlay";

        this._el=wrap;
        this._overlay=overlay;
    }

    //显示
    Msg.prototype._show=function([el,overlay]){
        document.body.appendChild(el);
        document.body.appendChild(overlay);

        //设置动画效果显示
        //延迟实现异步效果
        setTimeout(function(){
            el.style.transform='translate(-50%, -50%) scale(1, 1)';        
            overlay.style.opacity=1;    
        });

    }

    //绑定事件
    Msg.prototype._bind=function([el,overlay]){
        const _this=this;

        //隐藏事件
        const hideMsg=function(){
            el.style.transform='translate(-50%, -50%) scale(0, 0)';        
            overlay.style.opacity=0;

            //动画结束后移除元素(css里设置的动画时间是300ms)
            setTimeout(function(){
                document.body.removeChild(el);
                document.body.removeChild(overlay);
            },300);            
        }

        //取消事件
        const cancel=function(e){
            //如果传入了回调,则执行回调,参数是e
            _this.cancel && _this.cancel.call(this._cancel,e);
            hideMsg();
        }

        //确认事件
        const confirm=function(e){
            _this.confirm && _this.confirm.call(_this.confirm,e);
            hideMsg();
        }

        //点击遮罩
        overlay.addEventListener("click",hideMsg);

        //点击右上角叉叉
        el.querySelector(".msg-header .msg-header-close-button").addEventListener("click",hideMsg);

        //点击取消按钮
        el.querySelector(".msg-footer .msg-footer-cancel-button").addEventListener("click",cancel);

        //点击确认按钮
        el.querySelector(".msg-footer .msg-footer-confirm-button").addEventListener("click",confirm);
    }

    //挂到window上可全局访问
    window.$Msg=Msg;

})(window,document);
原文地址:https://www.cnblogs.com/chenyingying0/p/12563033.html