zoukankan      html  css  js  c++  java
  • js实现自定义弹窗

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

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

    海纳百川,有容乃大;壁立千仞,无欲则刚。人要有胸怀方能成大事,不要被欲望所驱使,方能风吹不动浪打不摇。 不积跬步无以至千里,不积小流无以成江海。从事技术工作,要时刻学习积累,即使不能一专多能也应术业有专攻,方能以不变应万变。
  • 相关阅读:
    脑洞大开的爬虫解决思路 转载:https://mp.weixin.qq.com/s/Bd-wz_RiRpYv8ufIbQTZDg
    js逆向某东滑块 转载 https://mp.weixin.qq.com/s/eZSTfduYS63-LOvkAofxqA
    不能爬小程序,叫什么会爬虫 【参考资料也要看】 https://mp.weixin.qq.com/s/oDG3k_qjMZaoygZmz9OUDw
    HDU6042 Journey with Knapsack
    HDU7073 Integers Have Friends 2.0
    CF1439C Greedy Shopping
    CF813E Army Creation
    POJ1322 Chocolate
    CF451E Devu and Flowers
    POJ3734 Blocks
  • 原文地址:https://www.cnblogs.com/websharehome/p/9438741.html
Copyright © 2011-2022 走看看