基于原生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 相关文章推荐
javascript 一段左右两边随屏滚动的代码
Jun 18 Javascript
JavaScript动态创建div属性和样式示例代码
Oct 09 Javascript
使用Jquery实现每日签到功能
Apr 03 Javascript
BootStrap中Datepicker控件带中文的js文件
Aug 10 Javascript
详解js中常规日期格式处理、月历渲染和倒计时函数
Dec 28 Javascript
jquery Form轻松实现文件上传
May 24 jQuery
vue-cli项目中使用echarts图表实例
Oct 22 Javascript
webpack4+react多页面架构的实现
Oct 25 Javascript
微信小程序实现bindtap等事件传参
Apr 08 Javascript
vue使用localStorage保存登录信息 适用于移动端、PC端
May 27 Javascript
Vue动态面包屑功能的实现方法
Jul 01 Javascript
javascript面向对象三大特征之封装实例详解
Jul 24 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配置参数总结
2013/06/14 PHP
Win10 下安装配置IIS + MySQL + nginx + php7.1.7
2017/08/04 PHP
Code: write(s,d) 输出连续字符串
2007/08/19 Javascript
jQuery 使用手册(五)
2009/09/23 Javascript
js 动态文字滚动的例子
2011/01/17 Javascript
javascript事件绑定学习要点
2016/03/09 Javascript
jQuery实现字体颜色渐变效果的方法
2017/03/29 jQuery
微信小程序 侧滑删除(左滑删除)
2017/05/23 Javascript
一个Java程序猿眼中的前后端分离以及Vue.js入门(推荐)
2019/04/19 Javascript
Vue组件通信的几种实现方法
2019/04/25 Javascript
京东优选小程序的实现代码示例
2020/02/25 Javascript
Vue 封装防刷新考试倒计时组件的实现
2020/06/05 Javascript
React+EggJs实现断点续传的示例代码
2020/07/07 Javascript
vue实现tab栏点击高亮效果
2020/08/19 Javascript
Python中的rfind()方法使用详解
2015/05/19 Python
Python中列表、字典、元组数据结构的简单学习笔记
2016/03/20 Python
Python入门之三角函数atan2()函数详解
2017/11/08 Python
Python装饰器限制函数运行时间超时则退出执行
2019/04/09 Python
Python中的几种矩阵乘法(小结)
2019/07/10 Python
详解Python中的正斜杠与反斜杠
2019/08/09 Python
Python 获取项目根路径的代码
2019/09/27 Python
Python趣味入门教程之循环语句while
2020/08/26 Python
python实现一个简单RPC框架的示例
2020/10/28 Python
英国袜子店:Sock Shop
2017/01/11 全球购物
美国顶级品牌男士大码服装店:DXL
2017/08/30 全球购物
美味咖啡的顶级烘焙师:Cafe Britt
2018/03/15 全球购物
教育局长自荐信范文
2013/12/22 职场文书
预备党员的自我评价
2014/03/12 职场文书
竞聘书格式及范文
2014/03/31 职场文书
优秀班主任申报材料
2014/12/16 职场文书
学生会招新宣传语
2015/07/13 职场文书
2016党员入党决心书
2015/09/22 职场文书
《分数的意义》教学反思
2016/02/20 职场文书
庭外和解协议书
2016/03/23 职场文书
如何写好一份优秀的工作总结?
2019/06/21 职场文书
Linux中文件的基本属性介绍
2022/06/01 Servers