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滑动门代码
Dec 19 Javascript
JS判定是否原生方法
Jul 22 Javascript
js获取当前路径的简单示例代码
Jan 08 Javascript
JavaScript中的对象序列化介绍
Dec 30 Javascript
jQuery validate插件实现ajax验证重复的2种方法
Jan 22 Javascript
JS获取地址栏参数的两种方法(简单实用)
Jun 14 Javascript
Spring Boot+AngularJS+BootStrap实现进度条示例代码
Mar 02 Javascript
jquery自定义显示消息数量
Dec 19 jQuery
vue拖拽排序插件vuedraggable使用方法详解
Aug 21 Javascript
解决cordova+vue 项目打包成APK应用遇到的问题
May 10 Javascript
JS使用cookie保存用户登录信息操作示例
May 30 Javascript
vue引入Excel表格插件的方法
Apr 28 Vue.js
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上传、管理照片示例
2006/10/09 PHP
PHP 年龄计算函数(精确到天)
2012/06/07 PHP
PHP获取当前日期所在星期(月份)的开始日期与结束日期(实现代码)
2013/06/18 PHP
Win7 64位系统下PHP连接Oracle数据库
2014/08/20 PHP
常见php数据文件缓存类汇总
2014/12/05 PHP
帝国cms常用标签汇总
2015/07/06 PHP
THINKPHP3.2使用soap连接webservice的解决方法
2017/12/13 PHP
TP5.0框架实现无限极回复功能的方法分析
2019/05/04 PHP
php DES加密算法实例分析
2019/09/18 PHP
JavaScript与C# Windows应用程序交互方法
2007/06/29 Javascript
用jquery统计子菜单的条数示例代码
2013/10/18 Javascript
脚本合并提升javascript性能示例
2014/02/24 Javascript
js从外部获取图片的实现方法
2016/08/05 Javascript
JS仿hao123导航页面图片轮播效果
2016/09/01 Javascript
jQuery实现的仿百度,仿谷歌搜索下拉框效果示例
2016/12/30 Javascript
Vue的路由动态重定向和导航守卫实例
2018/03/17 Javascript
深入理解javascript prototype的相关知识
2019/09/19 Javascript
Vue使用NProgress进度条的方法
2019/09/21 Javascript
解决vue动态下拉菜单 有数据未反应的问题
2020/08/06 Javascript
JS异步宏队列微队列原理详解
2020/09/09 Javascript
python保存字符串到文件的方法
2015/07/01 Python
Python计时相关操作详解【time,datetime】
2017/05/26 Python
python实现根据文件关键字进行切分为多个文件的示例
2018/12/10 Python
Python数据预处理之数据规范化(归一化)示例
2019/01/08 Python
python ctypes库2_指定参数类型和返回类型详解
2019/11/19 Python
在python中利用dict转json按输入顺序输出内容方式
2020/02/27 Python
Python爬虫实例——爬取美团美食数据
2020/07/15 Python
pycharm2020.1.2永久破解激活教程,实测有效
2020/10/29 Python
HTML5通过navigator.mediaDevices.getUserMedia调用手机摄像头问题
2020/04/27 HTML / CSS
应届毕业生专业个人求职自荐信格式
2013/11/20 职场文书
法律六进活动方案
2014/03/13 职场文书
高中班主任评语大全
2014/04/25 职场文书
2014年党支部承诺书
2014/05/30 职场文书
道歉信范文
2015/05/12 职场文书
2019年中学生的思想品德评语集锦
2019/12/19 职场文书
Python异常类型以及处理方法汇总
2021/06/05 Python