基于原生JS封装的Modal对话框插件的示例代码


Posted in Javascript onSeptember 09, 2020

基于原生JS封装Modal对话框插件,具体内容如下所示:

原生JS封装Modal对话框插件,个人用来学习原理与思想,只有简单的基本框架的实现,可在此基础上添加更多配置项

API配置

//基本语法
  let modal = ModalPlugin({
    //提示的标题信息
    title:'系统提示',
    //内容模板 字符串 /模板字符串/DOM元素对象
    template:null,
    //自定义按钮信息
    buttons:[{
      //按钮文字
      text:'确定',
      click(){
        //this:当前实例
      }
    }]
  })
  modal.open()//=>打开
  modal.close()//=>关闭

//基于发布订阅,实现回调函数的监听
  modal.on('input/open/close/dragstart/dragmove/dragend',[func])
		modal.fire(...)
  modal.off(...)

Modal插件核心功能的开发

导出

(function () {
  function ModalPlugin() {
    return 
  }

  // 浏览器直接导入,这样的方法是暴露到全局的
  window.ModalPlugin = ModalPlugin;
  //如果还需要支持ES6Module/CommonJS模块导入规范,在react项目当中,vue项目当中也想用
  if (typeof module !== 'undefined' && module.exports !== 'undefined') {//如果module不存在,typeof不会出错,会返回undefined
    module.exports = ModalPlugin;//CommonJS规范,只有在webpack环境下才支持
  }
})()

使用对象和函数创建实例

想使用创建对象的方式new ModalPlugin()创建实例或当做普通函数执行ModalPlugin(),创建实例,需要这样做

(function () {
  function ModalPlugin() {
    return new init()
  }
//想使用创建对象的方式`new ModalPlugin()`创建实例或当做普通函数执行`ModalPlugin()`,创建实例,需要这样做

  //类的原型: 公共的属性方法
  ModalPlugin.prototype = {
    constructor: ModalPlugin
  }

  function init() {}
  init.prototype = ModalPlugin.prototype;
  // 浏览器直接导入,这样的方法是暴露到全局的
  window.ModalPlugin = ModalPlugin;
  //如果还需要支持ES6Module/CommonJS模块导入规范,在react项目当中,vue项目当中也想用
  if (typeof module !== 'undefined' && module.exports !== 'undefined') {//如果module不存在,typeof不会出错,会返回undefined
    module.exports = ModalPlugin;//CommonJS规范,只有在webpack环境下才支持
  }
})()

配置项

//封装插件的时候,需要支持很多配置项,有的配置项不传递有默认值,此时我们千万不要一个个定义形参,用对象的方式传形参,好处是可以不传,而且可以不用考虑顺序
  function ModalPlugin(options) {
    return new init(options)
  }
//想使用创建对象的方式创建实例new ModalPlugin()或当做普通函数执行也能创建实例ModalPlugin(),需要这样做
  ModalPlugin.prototype = {
    constructor: ModalPlugin
  }

  function init(options) {
    //接下来将所有的操作全部写在init里面
    //参数初始化:传递进来的配置项替换默认的配置项
    options = Object.assign({
      title:'系统提示',
      template:null,
      frag:true,
      buttons:[{
        text:'确定',
        click(){
        }
      }]
    },options)

  }

命令模式init()执行逻辑

基于原生JS封装的Modal对话框插件的示例代码

创建DOM

//创建DOM结构
    creatDom(){
      //如果用creatElement插入DOM,每一次动态插入,都会导致DOM的回流,非常消耗性能,所以最外面使用createElement创建,内部使用字符串的方式拼写进去,创建好了之后放到最外层的容器当中,只引起一次回流
      let frag = document.createDocumentFragment()
      let dpnDialog = document.createElement('div')
      dpnDialog.className = 'dpn-dialog'
      dpnDialog.innerHTML = `
       <div class="dpn-title">
        系统温馨提示
        <i class="dpn-close"></i>
       </div>
       <div class="dpn-content">
      
       </div>
       <div class="dpn-handle">
        <button>确定</button>
        <button>取消</button>
       </div>`
      frag.appendChild(dpnDialog)

      let dpnModel = document.createElement('div')
      dpnModel.className = 'dpn-model'
      frag.appendChild(dpnModel)
      document.body.appendChild(frag)//使用frag只需要往页面中插入一次,减少回流次数
      frag = null

      this.dpnDialog = dpnDialog//挂载到实例上,便于其他方法的控制隐藏,并且是私有的实例,
      this.dpnModel = dpnModel
    }

对参数进行处理

基于原生JS封装的Modal对话框插件的示例代码

creatDom() {
      let {title, template, buttons} = this.options
      //如果用creatElement插入DOM,每一次动态插入,都会导致DOM的回流,非常消耗性能,所以最外面使用createElement创建,内部使用字符串的方式拼写进去,创建好了之后放到最外层的容器当中,只引起一次回流
      let frag = document.createDocumentFragment()
      let dpnDialog = document.createElement('div')
      dpnDialog.className = 'dpn-dialog'
      dpnDialog.innerHTML = `
       <div class="dpn-title">
        ${title}
        <i class="dpn-close">X</i>
       </div>
       <div class="dpn-content">
        ${template && typeof template === 'object' && template.nodeType === 1
        ? template.outerHTML
        : template}
       </div>
       ${buttons.length > 0
        ? `<div class="dpn-handle">
           ${buttons.map((item, index) => {
          return `<button index="${index}">${item.text}</button>`
        }).join('')}
          </div>`
        : ''
      }
       `
      frag.appendChild(dpnDialog)

      let dpnModel = document.createElement('div')
      dpnModel.className = 'dpn-model'
      frag.appendChild(dpnModel)
      document.body.appendChild(frag)//使用frag只需要往页面中插入一次,减少回流次数
      frag = null

      this.dpnDialog = dpnDialog//挂载到实例上,便于其他方法的控制隐藏,并且是私有的实例,
      this.dpnModel = dpnModel
    },

控制隐藏与显示

//控制他显示
    open() {
      this.dpnDialog.style.display = 'block'
      this.dpnModel.style.display = 'block'
    },
    //控制隐藏
    close() {
      this.dpnDialog.style.display = 'none'
      this.dpnModel.style.display = 'none'
    }

基于事件委托处理点击事件

基于原生JS封装的Modal对话框插件的示例代码

init() {
      this.creatDom()

      //基于事件委托,实现点击事件的处理
      this.dpnDialog.addEventListener('click', (ev)=>{
        let target = ev.target,
          {tagName,className}= target
        console.log([target])
        //点击的关闭按钮
        if(tagName==='I'&&className.includes('dpn-close')){
          this.close()
          return
        }
        //点击的是底部按钮
        if(tagName==='BUTTON' && target.parentNode.className.includes('dpn-handle')){
          let index = target.getAttribute('index')
          //让传过来的函数执行,并且函数中的this还必须是当前实例
          let func = this.options.buttons[index]['click']
          if(typeof func==='function'){
            func.call(this)
          }
          return
        }

      })
    },

基于发布订阅实现回调函数的监听(生命周期)

基于原生JS封装的Modal对话框插件的示例代码

基于原生JS封装的Modal对话框插件的示例代码
基于原生JS封装的Modal对话框插件的示例代码

//使用:
基于原生JS封装的Modal对话框插件的示例代码
基于原生JS封装的Modal对话框插件的示例代码

完整代码

//modalplugin.js
(function () {
  //封装插件的时候,需要支持很多配置项,有的配置项不传递有默认值,此时我们千万不要一个个定义形参,用对象的方式传形参,好处是可以不穿,而且可以不用考虑顺序
  function ModalPlugin(options) {
    return new init(options)
  }

//想使用创建对象的方式创建实例new ModalPlugin()或当做普通函数执行也能创建实例ModalPlugin(),需要这样做
  ModalPlugin.prototype = {
    constructor: ModalPlugin,
    //相当于大脑,可以控制先干什么在干什么(命令模式)
    init() {
      //创建DOM结构
      this.creatDom()

      //基于事件委托,实现点击事件的处理
      this.dpnDialog.addEventListener('click', (ev) => {
        let target = ev.target,
          {tagName, className} = target
        //点击的关闭按钮
        if (tagName === 'I' && className.includes('dpn-close')) {
          this.close()
          return
        }
        //点击的是底部按钮
        if (tagName === 'BUTTON' && target.parentNode.className.includes('dpn-handle')) {
          let index = target.getAttribute('index')
          //让传过来的函数执行,并且函数中的this还必须是当前实例
          let func = this.options.buttons[index]['click']
          if (typeof func === 'function') {
            func.call(this)
          }
          return
        }
      })
      this.fire('init')//通知init方法执行成功
    },
    //创建DOM结构
    creatDom() {
      let {title, template, buttons} = this.options
      //如果用creatElement插入DOM,每一次动态插入,都会导致DOM的回流,非常消耗性能,所以最外面使用createElement创建,内部使用字符串的方式拼写进去,创建好了之后放到最外层的容器当中,只引起一次回流
      let frag = document.createDocumentFragment()
      let dpnDialog = document.createElement('div')
      dpnDialog.className = 'dpn-dialog'
      dpnDialog.innerHTML = `
       <div class="dpn-title">
        ${title}
        <i class="dpn-close">X</i>
       </div>
       <div class="dpn-content">
        ${template && typeof template === 'object' && template.nodeType === 1
        ? template.outerHTML
        : template}
       </div>
       ${buttons.length > 0
        ? `<div class="dpn-handle">
           ${buttons.map((item, index) => {
          return `<button index="${index}">${item.text}</button>`
        }).join('')}
          </div>`
        : ''
      }
       `
      frag.appendChild(dpnDialog)

      let dpnModel = document.createElement('div')
      dpnModel.className = 'dpn-model'
      frag.appendChild(dpnModel)
      document.body.appendChild(frag)//使用frag只需要往页面中插入一次,减少回流次数
      frag = null

      this.dpnDialog = dpnDialog//挂载到实例上,便于其他方法的控制隐藏,并且是私有的实例,
      this.dpnModel = dpnModel
    },
    //控制他显示
    open() {
      this.dpnDialog.style.display = 'block'
      this.dpnModel.style.display = 'block'
      this.fire('open')//通知open方法执行成功
    },
    //控制隐藏
    close() {
      this.dpnDialog.style.display = 'none'
      this.dpnModel.style.display = 'none'
      this.fire('close')//通知close方法执行成功
    },
    //on向事件池中订阅方法
    on(type, func) {
      let arr = this.pond[type]
      if(arr.includes(func)) return
      arr.push(func)
    },
    //通知事件池中的方法执行
    fire(type) {
      let arr = this.pond[type]
      arr.forEach(item => {
        if(typeof item ==='function'){
          item.call(this)
        }
      })
    }

  }

  function init(options) {
    //接下来将所有的操作全部写在init里面
    //参数初始化:传递进来的配置项替换默认的配置项
    options = Object.assign({
      title: '系统提示',
      template: null,
      frag: true,
      buttons: [{}]
    }, options)
    //把信息挂载到实例上: 在原型的各个方法中,只要this是实例,都可以调用到这些信息
    this.options = options;
    this.pond = {
      init: [],
      close: [],
      open: []
    }
    this.init()
  }

  init.prototype = ModalPlugin.prototype;
  // 浏览器直接导入,这样的方法是暴露到全局的
  window.ModalPlugin = ModalPlugin;
  //如果还需要支持ES6Module/CommonJS模块导入规范,在react项目当中,vue项目当中也想用
  if (typeof module !== 'undefined' && module.exports !== 'undefined') {//如果module不存在,typeof不会出错,会返回undefined
    module.exports = ModalPlugin;//CommonJS规范,只有在webpack环境下才支持
  }
})()

使用

使用时需要引入modalpugin.jsmodalpugin.css

使用示例1:

//使用:
const modal1 = ModalPlugin({
  //提示的标题信息
  title: '系统提示',
  //内容模板 字符串 /模板字符串/DOM元素对象
  template: null,
  //自定义按钮信息
  buttons: [{
    //按钮文字
    text: '确定',
    click() {
      //this:当前实例
      this.close()
    }
  }, {
    //按钮文字
    text: '取消',
    click() {
      //this:当前实例
      this.close()
    },

  }]
})
modal1.on('open',()=>{
  console.log('我被打开了1')
})
modal1.on('open',()=>{
  console.log('我被打开了2')
})
modal1.on('close',()=>{
  console.log('我被关闭了')
})
modal1.open()

使用示例2:

基于原生JS封装的Modal对话框插件的示例代码

github

完整代码github

到此这篇关于基于原生JS封装的Modal对话框插件的示例代码的文章就介绍到这了,更多相关JS封装Modal对话框插件内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
c#+jquery实现获取radio和checkbox的值
Sep 12 Javascript
JavaScript日期时间与时间戳的转换函数分享
Jan 31 Javascript
浅谈js数据类型判断与数组判断
Aug 29 Javascript
Vue.js动态组件解析
Sep 09 Javascript
总结Javascript中数组各种去重的方法
Oct 04 Javascript
利用angular、react和vue实现相同的面试题组件
Feb 19 Javascript
jQuery 实现倒计时天,时,分,秒功能
Jul 31 jQuery
JavaScript栈和队列相关操作与实现方法详解
Dec 07 Javascript
JavaScript生成随机验证码代码实例
Sep 28 Javascript
Vue使用虚拟dom进行渲染view的方法
Dec 26 Javascript
vue element-ui实现input输入框金额数字添加千分位
Dec 29 Javascript
node crawler如何添加promise支持
Feb 01 Javascript
vue监听浏览器原生返回按钮,进行路由转跳操作
Sep 09 #Javascript
JS实现斐波那契数列的五种方式(小结)
Sep 09 #Javascript
JavaScript代码简化技巧实例解析
Sep 09 #Javascript
vue 手机物理监听键+退出提示代码
Sep 09 #Javascript
关于angular引入ng-zorro的问题浅析
Sep 09 #Javascript
关于vue的列表图片选中打钩操作
Sep 09 #Javascript
JavaScript日期库date-fn.js使用方法解析
Sep 09 #Javascript
You might like
PHP中SESSION使用中的一点经验总结
2012/03/30 PHP
JavaScript 实现??打印?理
2007/04/28 Javascript
Javascript 通过json自动生成Dom的代码
2010/04/01 Javascript
Javascript的setTimeout()使用闭包特性时需要注意的问题
2014/09/23 Javascript
基于jquery固定于顶部的导航响应浏览器滚动条事件
2014/11/02 Javascript
Javascript中Array用法实例分析
2015/06/13 Javascript
javascript 闭包详解
2015/07/02 Javascript
详解js中构造流程图的核心技术JsPlumb
2015/12/08 Javascript
浅谈jQuery中ajaxPrefilter的应用
2016/08/01 Javascript
总结JavaScript在IE9之前版本中内存泄露问题
2018/04/28 Javascript
Vue实现textarea固定输入行数与添加下划线样式的思路详解
2018/06/28 Javascript
详解如何在Angular优雅编写HTTP请求
2018/12/05 Javascript
webpack打包优化的几个方法总结
2020/02/10 Javascript
基于Element封装一个表格组件tableList的使用方法
2020/06/29 Javascript
JS绘图Flot如何实现可选显示曲线图功能
2020/10/16 Javascript
数据挖掘之Apriori算法详解和Python实现代码分享
2014/11/07 Python
python学习笔记之调用eval函数出现invalid syntax错误问题
2015/10/18 Python
python密码错误三次锁定(实例讲解)
2017/11/14 Python
Python实现PS图像抽象画风效果的方法
2018/01/23 Python
Python实现PS滤镜功能之波浪特效示例
2018/01/26 Python
Python闭包函数定义与用法分析
2018/07/20 Python
python程序需要编译吗
2020/06/19 Python
ubuntu16.04升级Python3.5到Python3.7的方法步骤
2020/08/20 Python
python调用百度API实现人脸识别
2020/11/17 Python
医科大学生的自我评价
2013/12/04 职场文书
硕士研究生求职自荐信范文
2014/03/11 职场文书
大学生应聘导游自荐信
2014/06/02 职场文书
汽修专业自荐信
2014/07/07 职场文书
总经理助理岗位职责范本
2014/07/20 职场文书
2014年党员学习“三严三实”思想汇报
2014/09/15 职场文书
作风整顿个人剖析材料
2014/10/06 职场文书
2015初中生物教研组工作总结
2015/07/21 职场文书
80后创业总结的9条职场用人思想,记得收藏
2019/08/13 职场文书
八年级作文之感悟亲情
2019/11/20 职场文书
微信小程序中wxs文件的一些妙用分享
2022/02/18 Javascript
SpringCloud Function SpEL注入漏洞分析及环境搭建
2022/04/08 Java/Android