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 相关文章推荐
实现复选框全选/全不选切换
Dec 23 Javascript
用Javascript评估用户输入密码的强度(Knockout版)
Nov 30 Javascript
js检测输入内容全为空格的方法
May 03 Javascript
jquery中push()的用法(数组添加元素)
Nov 25 Javascript
JSONP跨域GET请求解决Ajax跨域访问问题
Dec 31 Javascript
JS实现网页滚动条感应鼠标变色的方法
Feb 26 Javascript
基于JavaScript实现微信抢红包功能
Jul 20 Javascript
ES6中新增的Object.assign()方法详解
Sep 22 Javascript
浅谈JavaScript 代码简洁之道
Jan 09 Javascript
Vue CLI4 Vue.config.js标准配置(最全注释)
Jun 05 Javascript
vue实现下拉菜单树
Oct 22 Javascript
vue-router路由懒加载及实现的3种方式
Feb 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
150kHz到30Mhz完全冲浪手册
2020/03/20 无线电
PHP+Ajax异步通讯实现用户名邮箱验证是否已注册( 2种方法实现)
2011/12/28 PHP
php检查字符串中是否有外链的方法
2015/07/29 PHP
PHP微信分享开发详解
2017/01/14 PHP
php 函数中静态变量使用的问题实例分析
2020/03/05 PHP
Js 代码中,ajax请求地址后加随机数防止浏览器缓存的原因
2013/05/07 Javascript
简单的代码实现jquery定时器
2013/11/17 Javascript
jquery全选checkBox功能实现代码(取消全选功能)
2013/12/10 Javascript
Jquery插件编写简明教程
2014/03/25 Javascript
JavaScript函数参数使用带参数名的方式赋值传入的方法
2015/03/19 Javascript
jQuery实现的背景动态变化导航菜单效果
2015/08/24 Javascript
node.js中axios使用心得总结
2017/11/29 Javascript
vue中axios的封装问题(简易版拦截,get,post)
2018/06/15 Javascript
详解js获取video任意时间的画面截图
2019/04/17 Javascript
微信小程序实现消息框弹出动画
2020/04/18 Javascript
Postman如何实现参数化执行及断言处理
2020/07/28 Javascript
vue实现日历表格(element-ui)
2020/09/24 Javascript
Python对列表排序的方法实例分析
2015/05/16 Python
python实现自动获取IP并发送到邮箱
2018/12/26 Python
Python实现的读取文件内容并写入其他文件操作示例
2019/04/09 Python
django框架两个使用模板实例
2019/12/11 Python
如何使用python3获取当前路径及os.path.dirname的使用
2019/12/13 Python
Django中的session用法详解
2020/03/09 Python
如何使用Cython对python代码进行加密
2020/07/08 Python
python如何支持并发方法详解
2020/07/25 Python
纯CSS3实现绘制各种图形实现代码详细整理
2012/12/26 HTML / CSS
难忘的一课教学反思
2014/04/30 职场文书
初中成绩单评语
2014/12/29 职场文书
市场总监岗位职责
2015/02/11 职场文书
国庆节慰问信
2015/02/15 职场文书
会计求职简历自我评价
2015/03/10 职场文书
2015公务员年度考核评语
2015/03/25 职场文书
前端JavaScript大管家 package.json
2021/11/02 Javascript
Python帮你解决手机qq微信内存占用太多问题
2022/02/15 Python
SONY600GR,国产收音机厂商永远的痛
2022/04/05 无线电
Redis如何实现验证码发送 以及限制每日发送次数
2022/04/18 Redis