相思资源网 Design By www.200059.com
基于原生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()执行逻辑
创建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 }
对参数进行处理
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 "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' }
基于事件委托处理点击事件
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 } }) },
基于发布订阅实现回调函数的监听(生命周期)
完整代码
//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 "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.js
和modalpugin.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:
github
完整代码github
相思资源网 Design By www.200059.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
相思资源网 Design By www.200059.com
暂无基于原生JS封装的Modal对话框插件的示例代码的评论...
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?