基于原生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 相关文章推荐
在你的网页中嵌入外部网页的方法
Apr 02 Javascript
JavaScript中的排序算法代码
Feb 22 Javascript
解决jquery的datepicker的本地化以及Today问题
May 23 Javascript
js检测离开或刷新页面时表单数据是否更改的方法
Aug 02 Javascript
jQuery 如何实现一个滑动按钮开关
Dec 01 Javascript
如何防止INPUT按回车自动提交表单FORM
Dec 06 Javascript
从零开始学习Node.js系列教程五:服务器监听方法示例
Apr 13 Javascript
Vim快速合并行及vim 将文件所有行合并到一行
Nov 27 Javascript
vue中改变选中当前项的显示隐藏或者状态的实现方法
Feb 08 Javascript
Bootstrap4如何定制自己的颜色和风格
Feb 26 Javascript
vue+element实现表单校验功能
May 20 Javascript
Vue中axios的封装(报错、鉴权、跳转、拦截、提示)
Aug 20 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
浅析ThinkPHP中execute和query方法的区别
2014/06/13 PHP
PHP SESSION机制的理解与实例
2019/03/22 PHP
一次失败的jQuery优化尝试小结
2011/02/06 Javascript
innerText和textContent对比及使用介绍
2013/02/27 Javascript
删除javascript中注释语句的正则表达式
2014/06/11 Javascript
jQuery中选择器的基础使用教程
2016/05/23 Javascript
JS实现获取当前URL和来源URL的方法
2016/08/24 Javascript
jstree创建无限分级树的方法【基于ajax动态创建子节点】
2016/10/25 Javascript
AngularJS中的缓存使用
2017/01/11 Javascript
js实现符合国情的日期插件详解
2017/01/19 Javascript
详解angularjs中的隔离作用域理解以及绑定策略
2017/05/31 Javascript
详解Vue.js Mixins 混入使用
2017/09/15 Javascript
详解如何让Express支持async/await
2017/10/09 Javascript
vue-resource + json-server模拟数据的方法
2017/11/02 Javascript
vue+element实现批量删除功能的示例
2018/02/28 Javascript
解决修复npm安装全局模块权限的问题
2018/05/17 Javascript
Vue表单及表单绑定方法
2018/09/04 Javascript
深入浅析javascript函数中with
2018/10/28 Javascript
关于微信小程序map组件z-index的层级问题分析
2019/07/09 Javascript
JavaScript setInterval()与setTimeout()计时器
2019/12/27 Javascript
[01:01:43]EG vs VP 2018国际邀请赛淘汰赛BO3 第二场 8.24
2018/08/25 DOTA
[58:46]OG vs NAVI 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
python-numpy-指数分布实例详解
2019/12/07 Python
paramiko使用tail实时获取服务器的日志输出详解
2020/12/06 Python
css3动画效果小结(推荐)
2016/07/25 HTML / CSS
西班牙创意礼品和小工具网上商店:Curiosite
2016/07/26 全球购物
Hotels.com香港酒店网:你的自由行酒店订房专家
2018/01/22 全球购物
食品安全工作实施方案
2014/03/26 职场文书
公司应聘求职信
2014/06/21 职场文书
财务助理岗位职责范本
2014/10/09 职场文书
客户经理岗位职责大全
2015/04/09 职场文书
出纳试用期工作总结2015
2015/05/28 职场文书
孩子满月酒答谢词
2015/09/30 职场文书
2019年鼓励无偿献血倡议书
2019/09/17 职场文书
Python-OpenCV教程之图像的位运算详解
2021/06/21 Python
python 闭包函数详细介绍
2022/04/19 Python