工具-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 模式的浅显探索?
相关推荐
却尘6 分钟前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js
ccnocare7 分钟前
浅浅看一下设计模式
前端
Lee川11 分钟前
🎬 从标签到屏幕:揭秘现代网页构建与适配之道
前端·面试
Ticnix38 分钟前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人41 分钟前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl1 小时前
OpenClaw 深度技术解析
前端
崔庆才丨静觅1 小时前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人1 小时前
vue3使用jsx语法详解
前端·vue.js
天蓝色的鱼鱼1 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端
布列瑟农的星空1 小时前
前端都能看懂的Rust入门教程(三)——控制流语句
前端·后端·rust