工具-jquery封装弹框插件

一个文笔一般,想到哪是哪的唯心论前端小白。

前言

没错,跟jQuery磕上了!

前两天无奈之下用jQuery写了个分页,今天又写了一个弹框组件。没有特殊的地方,就是弹框组件,和 el-dialog 是一模一样的。

效果大概是这样子的:

觉得可能在不知道什么时候可能用一下,所以做个文档记录一下吧!

思路

需求分析:

  1. 通过点击dom对象,或者触发js方法,触发 open 方法,打开弹框。
  2. 弹框自动添加 header 和 footer,并把业务放在 body 中。
  3. 支持按钮自定义,并可以绑定自定义方法。自定义方法执行完成以后关闭弹框。

使用方法设想

根据最近的开发习惯,dom结构当然是这样的最舒服了!

html 复制代码
<div class="cm-dialog" id="dialogDemo">
    <p>hello world!</p>
</div>

即我们只关注业务内容,由插件动生成弹框的头部和底部。

然后是js结构则是这样的:

js 复制代码
 $(function () {
    const dialogDemo = $('#dialogDemo').initDialog({
        title: '查看详情',
        cancel: {
            label: '取消',
            handler: function () {
                console.log('触发了取消');
                return true;
            }
        },
        submit: {
            label: '确定',
            handler: function () {
                console.log('触发了确定');
                return true;
            }
        }
    })
    
    $('#button').on('click', function () {
        dialogDemo.trigger('open')
    })
})

可以看到,针对jQuery扩展了一个名为 initDialog 的方法,传入配置内容,配置内容包含常用的 title 和两个按钮,分别对应【取消】按钮和【确定】按钮,并绑定两个方法。

关键是最后要使用一个变量来记录这个初始化以后的 dialog 对象,可以使用 trigger 方法去触发内部的 open 方法,打开弹框。

坑点补充

以上这个方案里面有几个点需要注意:

  1. 如果按钮绑定的方法抛出异常,需要阻止关闭,所以这个方法应该有一个 Boolearn 类型的返回值。
  2. 如果只有一个按钮或者多个按钮,则需要动态的去渲染按钮。
  3. body 部分应该有个最大高度,避免超出可视范围的尴尬局面。

开发

开发这块比较简单,提前声明一下,上面三个坑点只有第三个做了,前面两个没做!

意不意外? 但是还会把思路写出来。

开发过程中因为没想明白怎么使用模版把 头部和底部 使用模板渲染出来,一度想着在 cm-dialog 里面再套一层,然后再向里面添加 htm 的方法,后来被 pass 掉了。

最终的方案是这样子的:

js 复制代码
$.fn.extend({
  initDialog: function (conf) {
    var inner = $(this).html();
    // 解析 config
    var title = conf.title || "标题";
    var cancel = conf.cancel || null;
    var submit = conf.submit || null;

    // 模板
    var htm = `
    <div class="cm-dialog-wrap">
      <div class="cm-dialog-header">
        <span>${title}</span>
      </div>
      <div class="cm-dialog-body">
        ${inner}
      </div>
      <div class="cm-dialog-footer">
        <button class="cm-button-cancel">${cancel.label}</button>
        <button class="cm-button-submit">${submit.label}</button>
      </div>
    </div>
    `;

    // 初始化 dialog
    $(this).html(htm);
    $(this).hide();

    // 绑定 open 方法
    $(this).bind("open", function () {
      $(this).fadeIn();
    });

    // 绑定 close 方法
    $(this).bind("close", function () {
      $(this).fadeOut();
    });

    // 绑定按钮事件
    $(".cm-button-cancel").on("click", function () {
      if(cancel.handler && cancel.handler()){
          $(this).trigger("close");
      };
    });
    $(".cm-button-submit").on("click", function () {
      if(submit.handler && submit.handler()){
          $(this).trigger("close");
      }
    });

    // 返回 dialog
    return $(this);
  },
});

其实结构很简单,主要是一个思路,就是在方法的一开始,将 inner 提出来,然后放在模板中。这样就实现了dom结构很简单,但是后面会包含头部和底部的开发方式。

然后就是剩余的两个坑点的处理方式:

  1. 其实已经解决了,返回值为 true 和false 的事情,但是如果是异步方法需要注意了,可以使用 trigger 去触发 close 方法。
  2. 传入按钮改为一个数组,使用map函数将数组转换成dom结构,并重新绑定一下方法就好了。

代码分享

主要分享三个文件:

dialog.extends.js

js 复制代码
$.fn.extend({
  initDialog: function (conf) {
    var inner = $(this).html();
    // 解析 config
    var title = conf.title || "标题";
    var cancel = conf.cancel || null;
    var submit = conf.submit || null;

    // 模板
    var htm = `
    <div class="cm-dialog-wrap">
      <div class="cm-dialog-header">
        <span>${title}</span>
      </div>
      <div class="cm-dialog-body">
        ${inner}
      </div>
      <div class="cm-dialog-footer">
        <button class="cm-button-cancel">${cancel.label}</button>
        <button class="cm-button-submit">${submit.label}</button>
      </div>
    </div>
    `;

    // 初始化 dialog
    $(this).html(htm);
    $(this).hide();

    // 绑定 open 方法
    $(this).bind("open", function () {
      $(this).fadeIn();
    });

    // 绑定 close 方法
    $(this).bind("close", function () {
      $(this).fadeOut();
    });

    // 绑定按钮事件
    $(".cm-button-cancel").on("click", function () {
      if(cancel.handler && cancel.handler()){
          $(this).trigger("close");
      };
    });
    $(".cm-button-submit").on("click", function () {
      if(submit.handler && submit.handler()){
          $(this).trigger("close");
      }
    });

    // 返回 dialog
    return $(this);
  },
});

dialog.extends.css

需要注意,这里只包含了 dialog 相关的样式,需要配合全局样式去使用。

类似:*{ padding :0; margin: 0}

css 复制代码
.cm-dialog {
  height: 100%;
  width: 100%;

  position: fixed;
  z-index: 999;
  top: 0;
  left: 0;

  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;

  background: rgba(48, 42, 42, 0.5);
}

.cm-dialog-wrap {
  height: auto;
  width: 960px;
  background: #fff;
  box-shadow: 0 0 10px #000;

  position: relative;
  overflow: hidden;
}

.cm-dialog-header {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  padding: 5px 20px;

  background: #ebecee;
  height: 40px;
  line-height: 40px;
}

.cm-dialog-body {
  padding: 70px 20px 70px 20px;

  max-height: 500px;
  overflow-y: auto;
  overflow-x: hidden;
}

.cm-dialog-footer {
  position: absolute;
  bottom: 0;
  background: #ebecee;

  padding: 5px 20px;
  left: 0;
  right: 0;
  line-height: 40px;
  text-align: right;
}

.cm-dialog-footer button {
  padding: 6px 16px;

  background: skyblue;
  border: none;
  outline: none;
  border-radius: 4px;
  cursor: pointer;

  transition: background linear 0.1s;
}

/* .cm-dialog-footer button.cm-button-submit {
    background: red;
  } */

.cm-dialog-footer button:hover {
  background: rgb(58, 182, 231);
}

dialog-demo.html

就是展示一下怎么用。

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./index.css">
    <link rel="stylesheet" href="./dialog.extend.css">
</head>

<body>
    <button id="button">Click Me!</button>


    <div class="cm-dialog" id="dialogDemo">
        <p>hello world!</p>
    </div>
</body>

<script src="./jquery.js"></script>
<script src="./dialog.extends.js"></script>
<script>

    $(function () {
        const dialogDemo = $('#dialogDemo').initDialog({
            title: '查看详情',
            cancel: {
                label: '取消',
                handler: function () {
                    console.log('触发了取消');
                }
            },
            submit: {
                label: '确定',
                handler: function () {
                    console.log('触发了确定');
                }
            }

        })

        $('#button').on('click', function () {
            dialogDemo.trigger('open')
        })
    })
</script>

</html>

后记

思路很简单,代码量也很少,关键就是一个将原模板里面的内容重写一遍的思路。

有所思必有所得:

  1. 一个开箱即用的 dialog jQuery 插件。
  2. 一个 jQuery 或者原生代码中使用模板开发的开发思路。
  3. MVVM 模式的浅显探索?
相关推荐
一斤代码2 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子2 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年2 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子3 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina3 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路4 小时前
React--Fiber 架构
前端·react.js·架构
coderlin_4 小时前
BI布局拖拽 (1) 深入react-gird-layout源码
android·javascript·react.js
伍哥的传说4 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js
qq_424409194 小时前
uniapp的app项目,某个页面长时间无操作,返回首页
前端·vue.js·uni-app
我在北京coding4 小时前
element el-table渲染二维对象数组
前端·javascript·vue.js