工具-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 分钟前
【HTML5】轮播图的实现方式一
前端·javascript·css·html·html5
源码方舟6 分钟前
【HTML5】老式放映机原理-实现图片无缝滚动
前端·javascript·css·html·css3·html5
梦想与想象-广州大智汇1 小时前
普通 html 项目引入 tailwindcss
前端·html·tailwindcss
钢铁男儿3 小时前
C# 类成员与访问修饰符:面向对象编程的核心概念解析
java·javascript·c#
立秋67893 小时前
3D人物关系图开发实战:Three.js实现自动旋转可视化图谱(附完整代码)
开发语言·javascript·3d
lh_12544 小时前
前端 uni-app 初步使用指南
前端·arcgis·uni-app
患得患失9494 小时前
【前端】【面试】在 Nuxt.js SSR/SSG 应用开发的 SEO 优化方面,你采取了哪些具体措施来提高页面在搜索引擎中的排名?
前端·javascript·搜索引擎
layman05284 小时前
ES6/ES11知识点 续二
前端·ecmascript·es6
ejinxian5 小时前
npm,yarn,pnpm,cnpm,nvm,npx包管理器常用命令
前端·npm·pnpm·yarn·nvm·npx
爱编程的鱼5 小时前
C# 运算符重载深度解析:从基础到高阶实践
前端·算法·c#