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 相关文章推荐
javascript编程起步(第七课)
Jan 10 Javascript
jquery中的过滤操作详细解析
Dec 02 Javascript
Jquery实现瀑布流布局(备有详细注释)
Jul 31 Javascript
在Ubuntu系统上安装Node.JS的教程
Oct 15 Javascript
每日十条JavaScript经验技巧(二)
Jun 23 Javascript
基于jQuery实现淡入淡出效果轮播图
Jul 31 Javascript
AngularJS 模块化详解及实例代码
Sep 14 Javascript
JavaScript仿网易选项卡制作代码
Oct 06 Javascript
JavaScript函数表达式详解及实例
May 05 Javascript
Vue2单一事件管理组件通信
May 09 Javascript
Vue 实现显示/隐藏层的思路(加全局点击事件)
Dec 31 Javascript
基于vue的video播放器的实现示例
Feb 19 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
vBulletin Forum 2.3.xx SQL Injection
2006/10/09 PHP
对squid中refresh_pattern的一些理解和建议
2009/04/17 PHP
PHP面向对象程序设计之接口用法
2014/08/20 PHP
PHP实现用户异地登录提醒功能的方法【基于thinkPHP框架】
2018/03/15 PHP
TP3.2.3框架使用CKeditor编辑器在页面中上传图片的方法分析
2019/12/31 PHP
PHP数据源架构模式之表入口模式实例分析
2020/01/23 PHP
在js中使用&quot;with&quot;语句中跨frame的变量引用问题
2007/03/08 Javascript
JS控制图片等比例缩放的示例代码
2013/12/24 Javascript
jquery让返回的内容显示在特定div里(代码少而精悍)
2014/06/23 Javascript
js的toUpperCase方法用法实例
2015/01/27 Javascript
js设置document.domain实现跨域的注意点分析
2015/05/21 Javascript
Nodejs的express使用教程
2015/11/23 NodeJs
有关jquery与DOM节点操作方法和属性记录
2016/04/15 Javascript
使用JQuery选择HTML遍历函数的方法
2016/09/17 Javascript
javascript中的后退和刷新实现方法
2016/11/10 Javascript
有趣的bootstrap走动进度条
2016/12/01 Javascript
bootstrap输入框组件使用方法详解
2017/01/19 Javascript
在node.js中怎么屏蔽掉favicon.ico的请求
2017/03/01 Javascript
js实现按座位号抽奖
2017/04/05 Javascript
angular 组件通信的几种实现方式
2018/07/13 Javascript
JavaScript对JSON数组简单排序操作示例
2019/01/31 Javascript
js实现盒子拖拽动画效果
2020/08/09 Javascript
如何使用gpu.js改善JavaScript的性能
2020/12/01 Javascript
react中hook介绍以及使用教程
2020/12/11 Javascript
Python编写生成验证码的脚本的教程
2015/05/04 Python
django 使用 request 获取浏览器发送的参数示例代码
2018/06/11 Python
python获取引用对象的个数方式
2019/12/20 Python
keras自定义损失函数并且模型加载的写法介绍
2020/06/15 Python
Pycharm安装第三方库失败解决方案
2020/11/17 Python
详解基于Facecognition+Opencv快速搭建人脸识别及跟踪应用
2021/01/21 Python
韩国女装NO.1网店:STYLENANDA
2016/09/16 全球购物
国际奢侈品品牌童装购物网站:Designer Childrenswear
2019/05/08 全球购物
西班牙语在线票务市场:SuperBoletería
2019/06/10 全球购物
Erwin Müller穆勒家居瑞士官网:您整个家庭的邮购公司
2019/12/28 全球购物
某某幼儿园的教育教学管理调研分析报告
2019/11/29 职场文书
JavaScript小技巧带你提升你的代码技能
2021/09/15 Javascript