JS实现自定义弹窗功能


Posted in Javascript onAugust 08, 2018

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

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以及css或者直接把相关代码加到自己的公共js中即可直接调用,注意,构造函数调用要用new.

总结

以上所述是小编给大家介绍的JS实现自定义弹窗功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
js表格分页实现代码
Sep 18 Javascript
js简单实现交换Li的值
May 22 Javascript
JScript中的条件注释详解
Apr 24 Javascript
微信小程序 小程序制作及动画(animation样式)详解
Jan 06 Javascript
jQuery插件zTree实现的多选树效果示例
Mar 08 Javascript
Vue表单验证插件Vue Validator使用方法详解
Apr 07 Javascript
关于Vue在ie10下空白页的debug小结
May 02 Javascript
详解微信小程序之一键复制到剪切板
Apr 24 Javascript
基于layui框架响应式布局的一些使用详解
Sep 16 Javascript
详解BootStrap表单验证中重置BootStrap-select验证提示不清除的坑
Sep 17 Javascript
javascript实现评分功能
Jun 24 Javascript
JS实现页面侧边栏效果探究
Jan 08 Javascript
vue.js提交按钮时进行简单的if判断表达式详解
Aug 08 #Javascript
解决jquery的ajax调取后端数据成功却渲染失败的问题
Aug 08 #jQuery
JS+HTML5实现获取手机验证码倒计时按钮
Aug 08 #Javascript
JS的Ajax与后端交互数据的实例
Aug 08 #Javascript
jquery 通过ajax请求获取后台数据显示在表格上的方法
Aug 08 #jQuery
JavaScript中arguments和this对象用法分析
Aug 08 #Javascript
利用js将ajax获取到的后台数据动态加载至网页中的方法
Aug 08 #Javascript
You might like
PHP实现查询两个数组中不同元素的方法
2016/02/23 PHP
PHP7 错误处理机制修改
2021/03/09 PHP
input、button的不同type值在ajax提交表单时导致的陷阱
2009/02/24 Javascript
JavaScript 放大镜 放大倍率和视窗尺寸
2011/05/09 Javascript
基于jquery的图片幻灯展示源码
2012/07/15 Javascript
jquery绑定事件不生效的解决方法
2014/02/11 Javascript
textarea焦点的用法实现获取焦点清空失去焦点提示效果
2014/05/19 Javascript
jquery让返回的内容显示在特定div里(代码少而精悍)
2014/06/23 Javascript
JavaScript基于setTimeout实现计数的方法
2015/05/08 Javascript
jquery实现左右滑动菜单效果代码
2015/08/27 Javascript
js游戏人物上下左右跑步效果代码分享
2015/08/28 Javascript
基于JQuery实现图片轮播效果(焦点图)
2016/02/02 Javascript
jquery插件Jplayer使用方法简析
2016/04/22 Javascript
js实现的简单图片浮动效果完整实例
2016/05/10 Javascript
AngularJS中的表单简单入门
2016/07/28 Javascript
JS控制div跳转到指定的位置的几种解决方案总结
2016/11/05 Javascript
HTML5+JS+JQuery+ECharts实现异步加载问题
2017/12/16 jQuery
vue.js与element-ui实现菜单树形结构的解决方法
2018/04/21 Javascript
微信小程序 wepy框架与iview-weapp的用法详解
2019/04/10 Javascript
python excel使用xlutils类库实现追加写功能的方法
2018/05/02 Python
python 五子棋如何获得鼠标点击坐标
2019/11/04 Python
如何用python免费看美剧
2020/08/11 Python
python 基于UDP协议套接字通信的实现
2021/01/22 Python
WEB控件及HTML服务端控件能否调用客户端方法?如果能,请解释如何调用?
2015/08/25 面试题
应届生会计求职信
2013/11/11 职场文书
政风行风建设责任书
2014/07/23 职场文书
酒店管理失职检讨书
2014/09/16 职场文书
经理聘任证明
2015/03/02 职场文书
2015年上半年信访工作总结
2015/03/30 职场文书
2015年保洁工作总结范文
2015/04/28 职场文书
创建文明城市倡议书
2015/04/28 职场文书
公司回复函格式
2015/07/14 职场文书
同学聚会致辞集锦
2015/07/28 职场文书
《纸船和风筝》教学反思
2016/02/18 职场文书
初中政治教学反思
2016/02/23 职场文书
创业计划书之暑假培训班
2019/11/09 职场文书