ES6 弹窗组件
<!DOCTYPE html> <html lang="en"> <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>Document</title> <style> .k-dialog { width: 30%; z-index: 2001; display: block; position: absolute; background: #fff; border-radius: 2px; box-shadow: 0 1px 3px rgba(0, 0, 0, .3); margin: 0 auto; top: 15vh; left:30%; } .k-wrapper { position: fixed; left: 0px; top: 0px; bottom: 0px; right: 0px; background: black; opacity: 0.4; z-index: 2000; } .k-header { padding: 20px 20px 10px; } .k-header .k-title { line-height: 24px; font-size: 18px; color: #303133; float: left; } .k-body { padding: 30px 20px; color: #606266; font-size: 14px; } .k-footer { padding: 10px 20px 30px; text-align: right; } .k-close { color: #909399; font-weight: 400; float: right; cursor: pointer; } .k-default { color: #606266; border: 1px solid #dcdfe6; text-align: center; cursor: pointer; padding: 12px 20px; font-size: 14px; border-radius: 4px; font-weight: 500; margin-right: 10px; } .k-default:hover { color: #409eff; background: #ecf5ff; border-color: #c6e2ff; } .k-primary { border: 1px solid #dcdfe6; text-align: center; cursor: pointer; padding: 12px 20px; font-size: 14px; border-radius: 4px; font-weight: 500; background: #409eff; color: #fff; margin-left: 10px; } .k-primary:hover { background: #66b1ff; } .k-input{ width: 100%; margin-left: 20px; margin-bottom: 20px; } .input-inner { -webkit-appearance: none; background-color: #fff; background-image: none; border-radius: 4px; border: 1px solid #dcdfe6; box-sizing: border-box; color: #606266; display: inline-block; font-size: inherit; height: 40px; line-height: 40px; outline: none; padding: 0 15px; transition: border-color .2s cubic-bezier(.645, .045, .355, 1); width: 100%; margin-top: 20px; } </style> </head> <body> <!-- <div class="k-wrapper"></div> <div class="k-dialog"> <div class="k-header"> <span class="k-title">提示</span><span class="k-close">X</span> </div> <div class="k-body"> <span>这是一段文本</span> <input class="input-inner" type="text" /> </div> <div class="k-footer"> <span class="k-default">取消</span> <span class="k-primary">确定</span> </div> </div> --> <button class="btn">点击显示对话框</button> <script src="./js/dialog.js" type="text/javascript"></script> <script> let dialog = new Dialog({ width:"40%", height:"400px", title:"测试标题111", content:"测试内容111", dragable:true,//是否可拖拽 maskable:true,//是否有遮罩 isCancel:true,//是否有取消 cancel(){ console.log("我点击了取消~") }, sucess(){ console.log("我点击了确定~") } }); document.querySelector(".btn").onclick = function(){ dialog.open(); } </script> </body> </html>
/* 别人如何引用我们写的组件呢? 1.js文件 2.css文件 3.js代码: 1.new 类(参数); 参数->需求 2.组件标签 弹窗组件代码解析: 1.创建类 2.默认参数 配置参数 配置项 在使用类的时候,不需要全部配置都传进去,也可以只传一个或者不传也达到可以执行效果. Object.assign 两个对象合并为一个对象,有相同的就以后面的为主 第一个对象是默认值 第二个对象代替第一项 解构赋值 默认参数:(width="30%",height="250px",title="测试标题"...) = options; 3.生成dom结构 createHtml(); 1.创建div 2.div放置元素 3.body放入div appendChild 4.创建了之后也是一个隐藏状态 div.display none 在点击按钮的时候才显示 4.初始化函数 init(); 一些一开始就调用的方法放到这里面 1.实例化完类先调用 this.init(); 5.显示对话框 open() 这个方法当用户进行单击的时候执行; 注:找元素,不要使用document.querySelector(""), 应该使用 this.div 6.对传进来的内容做呈现 在createHtml,init方法中进行判断... 1.标题,内容 -> this.opts.title this.opts.content 2.宽高 -> style="" 3.遮罩层判断 -> 在init中if(this.opts.maskable)...; this.div.querySelector("....").disp none 4.是否有取消 -> 在dom结构进行三目运算: ${this.opts.isCancel?`<span class="k-default">取消</span>`:``} 7.关闭对话框 close(); this.div none init -> 元素(取消).点击执行close(); 取消按钮: 判断是否有此节点 8.关闭对话框2 事件委托 这三个事件都是在div身上发生的,所以可以使用事件委托: this.div.onclick = e=>{ console.log(e.target); } 若假如有多个className可以使用正则来搞定,但一般情况下,这个组件是自己封装的是完全可控的; 取消与确定按钮的回调函数: 1.默认配置也要有这两个回调函数 cancel(){}, sucess(){} 2.再点击的时候执行此函数呗... 9.是否可以拖拽: drag(); 1.先写拖拽函数 2.在init判断是否可以拖拽 */ class Dialog{ constructor(option){ this.opts = Object.assign({ width:"30%", height:"250px", title:"测试标题", content:"测试内容", dragable:true,//是否可拖拽 maskable:true,//是否有遮罩 isCancel:false,//是否有取消 cancel(){}, sucess(){} },option); this.init(); } init(){ this.createHtml(); if(!this.opts.maskable){ this.div.querySelector(".k-wrapper").style.display = "none"; } /* this.div.querySelector(".k-close").onclick = ()=>{ this.close(); } this.div.querySelector(".k-default").onclick = ()=>{ this.close(); } */ this.div.onclick = e=>{ // console.log(e.target); switch(e.target.className){ case "k-close": this.close(); break; case "k-default": this.close(); this.opts.cancel(); break; case "k-primary": this.close(); this.opts.sucess(); break; default : console.log("没点中~"); break; } }; if(this.opts.dragable){ this.drag(); } } createHtml(){ this.div = document.createElement("div"); this.div.innerHTML = ` <div class="k-wrapper"></div> <div class="k-dialog" style="width:${this.opts.width}; height:${this.opts.height};"> <div class="k-header"> <span class="k-title">${this.opts.title}</span><span class="k-close">X</span> </div> <div class="k-body"> <span>${this.opts.content}</span> </div> <div class="k-footer"> ${this.opts.isCancel?`<span class="k-default">取消</span>`:``} <span class="k-primary">确定</span> </div> </div> `; this.div.style.display = "none"; document.querySelector("body").appendChild(this.div); } // 显示对话框 open(){ this.div.style.display = "block"; } // 关闭对话框 close(){ this.div.style.display = "none"; } // 拖拽 drag(){ let kDialog = this.div.querySelector(".k-dialog"); kDialog.onmousedown = e=>{ let x = e.clientX - kDialog.offsetLeft; let y = e.clientY - kDialog.offsetTop; document.onmousemove = e=>{ let xx = e.clientX - x; let yy = e.clientY - y; console.log(xx,yy) kDialog.style.left = xx + "px"; kDialog.style.top = yy + "px"; } document.onmouseup = function(){ document.onmousemove = null; } } } }
扩展内容
<!DOCTYPE html> <html lang="en"> <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>Document</title> <style> .k-dialog { width: 30%; z-index: 2001; display: block; position: absolute; background: #fff; border-radius: 2px; box-shadow: 0 1px 3px rgba(0, 0, 0, .3); margin: 0 auto; top: 15vh; left:30%; } .k-wrapper { position: fixed; left: 0px; top: 0px; bottom: 0px; right: 0px; background: black; opacity: 0.4; z-index: 2000; } .k-header { padding: 20px 20px 10px; } .k-header .k-title { line-height: 24px; font-size: 18px; color: #303133; float: left; } .k-body { padding: 30px 20px; color: #606266; font-size: 14px; } .k-footer { padding: 10px 20px 30px; text-align: right; } .k-close { color: #909399; font-weight: 400; float: right; cursor: pointer; } .k-default { color: #606266; border: 1px solid #dcdfe6; text-align: center; cursor: pointer; padding: 12px 20px; font-size: 14px; border-radius: 4px; font-weight: 500; margin-right: 10px; } .k-default:hover { color: #409eff; background: #ecf5ff; border-color: #c6e2ff; } .k-primary { border: 1px solid #dcdfe6; text-align: center; cursor: pointer; padding: 12px 20px; font-size: 14px; border-radius: 4px; font-weight: 500; background: #409eff; color: #fff; margin-left: 10px; } .k-primary:hover { background: #66b1ff; } .k-input{ width: 100%; margin-left: 20px; margin-bottom: 20px; } .input-inner { -webkit-appearance: none; background-color: #fff; background-image: none; border-radius: 4px; border: 1px solid #dcdfe6; box-sizing: border-box; color: #606266; display: inline-block; font-size: inherit; height: 40px; line-height: 40px; outline: none; padding: 0 15px; transition: border-color .2s cubic-bezier(.645, .045, .355, 1); width: 100%; margin-top: 20px; } </style> </head> <body> <!-- <div class="k-wrapper"></div> <div class="k-dialog"> <div class="k-header"> <span class="k-title">提示</span><span class="k-close">X</span> </div> <div class="k-body"> <span>这是一段文本</span> <input class="input-inner" type="text" /> </div> <div class="k-footer"> <span class="k-default">取消</span> <span class="k-primary">确定</span> </div> </div> --> <button class="btn">点击显示对话框</button> <button class="btn2">点击显示带输入框的对话框</button> <show-dialog width="40%" height="300px" title="自定义组件标题" >自定义组件弹框</show-dialog> <script src="./js/dialog.js" type="text/javascript"></script> <script> let dialog = new Dialog({ width:"40%", height:"220px", title:"测试标题111", content:"测试内容111", dragable:true,//是否可拖拽 maskable:true,//是否有遮罩 isCancel:true,//是否有取消 cancel(){ console.log("我点击了取消~") }, sucess(){ console.log("我是页面中的回调:点击了确定~"); } }); document.querySelector(".btn").onclick = function(){ dialog.open(); } let dialog2 = new ExtendsDialog({ width:"40%", height:"220px", title:"测试标题222", content:"测试内容222", dragable:true,//是否可拖拽 maskable:true,//是否有遮罩 isCancel:true,//是否有取消 cancel(){ console.log("我点击了取消~,第二个") }, sucess(e){ console.log(e); console.log("我是页面中的回调:点击了确定~,第二个值为:",e.detail); } }); document.querySelector(".btn2").onclick = function(){ dialog2.open(); } </script> </body> </html>
/* 别人如何引用我们写的组件呢? 1.js文件 2.css文件 3.js代码: 1.new 类(参数); 参数->需求 2.组件标签 弹窗组件代码解析: 1.创建类 2.默认参数 配置参数 配置项 在使用类的时候,不需要全部配置都传进去,也可以只传一个或者不传也达到可以执行效果. Object.assign 两个对象合并为一个对象,有相同的就以后面的为主 第一个对象是默认值 第二个对象代替第一项 解构赋值 默认参数:(width="30%",height="250px",title="测试标题"...) = options; 3.生成dom结构 createHtml(); 1.创建div 2.div放置元素 3.body放入div appendChild 4.创建了之后也是一个隐藏状态 div.display none 在点击按钮的时候才显示 4.初始化函数 init(); 一些一开始就调用的方法放到这里面 1.实例化完类先调用 this.init(); 5.显示对话框 open() 这个方法当用户进行单击的时候执行; 注:找元素,不要使用document.querySelector(""), 应该使用 this.div 6.对传进来的内容做呈现 在createHtml,init方法中进行判断... 1.标题,内容 -> this.opts.title this.opts.content 2.宽高 -> style="" 3.遮罩层判断 -> 在init中if(this.opts.maskable)...; this.div.querySelector("....").disp none 4.是否有取消 -> 在dom结构进行三目运算: ${this.opts.isCancel?`<span class="k-default">取消</span>`:``} 7.关闭对话框 close(); this.div none init -> 元素(取消).点击执行close(); 取消按钮: 判断是否有此节点 8.关闭对话框2 事件委托 这三个事件都是在div身上发生的,所以可以使用事件委托: this.div.onclick = e=>{ console.log(e.target); } 若假如有多个className可以使用正则来搞定,但一般情况下,这个组件是自己封装的是完全可控的; 取消与确定按钮的回调函数: 1.默认配置也要有这两个回调函数 cancel(){}, sucess(){} 2.再点击的时候执行此函数呗... 9.是否可以拖拽: drag(); 1.先写拖拽函数 2.在init判断是否可以拖拽 10.确认功能拆分:sure(); 组件开发功能划分的越细,后面的扩展更方便; 11.使用自定义事件,绑定一些事件 EventTarget 这是 系统 自己做了封装处理了; https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget 1.继承 extends EventTarget 2.super(); 3.绑定:addEventListener this.addEventListener("close",this.close); this.addEventListener("close",()=>{console.log("使用了自定义事件触发了,close")}); 4.触发: 稍微麻烦一点,需要实例化一下 let close = new CustomEvent("close"); this.dispatchEvent(close); 12.带input框的组件新功能的增加 若不想改变原来的东西,例游戏更新版本更新,更新失败后我们可以用版本回撤,原来版本不会发生改变; 所以这里使用继承类 ExtendsDialog 1.继承 extends super(); 2.参数 option 3.input的添加 找到对应的函数 createHtml(); 1.继承此函数: super.createHtml(); 2.创建input放到对应位置: let myInput = document.createElement("input"); myInput.type = "text"; myInput.classList.add("input-inner"); this.div.querySelector("k-body").appendChild(myInput); 尽可能少改变我们原来的 类 实现我们的功能; 4.点击确定 在回调中获取输入框内容的; 1.子类调用的时候传给父类 super.sure(value); 2.父类接收; sure(value); 3.使用自定义事件传递 let sucess = new CustomEvent("sucess",{ detail:value }); 4.回调接收参数; sucess(e){ console.log(e); console.log("我是页面中的回调:点击了确定~,第二个值为:",e.detail); } 不适用detail当然简单的方式也有: this.opts.sucess(value); 13.引用方式也可以进行 模块化 14.标签形式调用方式 -> 自定义组件: 例如vue: <my-dialog width="40%" title="测试标题" ></my-dialog> 直接把配置放到属性中 如何模拟这样的调用方式呢: webComponent https://www.cnblogs.com/Afanadmin/p/12381393.html 1.获取节点属性: attributes: let attr = this.attributes; 2.传递节点属性进入对话框; 1.判断是否有输入属性 let width = this.hasAttribute("width")?attr.width.value:"40%"; */ class Dialog extends EventTarget{ constructor(options){ super(); this.opts = Object.assign({ width:"30%", height:"250px", title:"测试标题", content:"测试内容", dragable:true,//是否可拖拽 maskable:true,//是否有遮罩 isCancel:false,//是否有取消 cancel(){}, sucess(){} },options); this.init(); } init(){ this.createHtml(); if(!this.opts.maskable){ this.div.querySelector(".k-wrapper").style.display = "none"; } /* this.div.querySelector(".k-close").onclick = ()=>{ this.close(); } this.div.querySelector(".k-default").onclick = ()=>{ this.close(); } */ // 绑定事件; this.addEventListener("close",this.close); this.addEventListener("close",()=>{console.log("使用了自定义事件触发了,close")}); // 确定按钮回调函数 绑定自定义事件; this.addEventListener("sucess",this.opts.sucess); this.div.onclick = e=>{ // console.log(e.target); switch(e.target.className){ case "k-close": // this.close(); let close = new CustomEvent("close"); this.dispatchEvent(close); break; case "k-default": this.close(); this.opts.cancel(); break; case "k-primary": // 确认按钮 this.sure(); break; default : console.log("没点中~"); break; } }; if(this.opts.dragable){ this.drag(); } } sure(value){//2.父类接收 // this.close(); // this.opts.sucess(); let close = new CustomEvent("close"); this.dispatchEvent(close); let sucess = new CustomEvent("sucess",{ detail:value }); this.dispatchEvent(sucess); } createHtml(){ this.div = document.createElement("div"); this.div.innerHTML = ` <div class="k-wrapper"></div> <div class="k-dialog" style="width:${this.opts.width}; height:${this.opts.height};"> <div class="k-header"> <span class="k-title">${this.opts.title}</span><span class="k-close">X</span> </div> <div class="k-body"> <span>${this.opts.content}</span> </div> <div class="k-footer"> ${this.opts.isCancel?`<span class="k-default">取消</span>`:``} <span class="k-primary">确定</span> </div> </div> `; this.div.style.display = "none"; document.querySelector("body").appendChild(this.div); } // 显示对话框 open(){ this.div.style.display = "block"; } // 关闭对话框 close(){ this.div.style.display = "none"; } // 拖拽 drag(){ let kDialog = this.div.querySelector(".k-dialog"); kDialog.onmousedown = e=>{ let x = e.clientX - kDialog.offsetLeft; let y = e.clientY - kDialog.offsetTop; if(e.target.className !== "input-inner"){ document.onmousemove = e=>{ let xx = e.clientX - x; let yy = e.clientY - y; kDialog.style.left = xx + "px"; kDialog.style.top = yy + "px"; } document.onmouseup = function(){ document.onmousemove = null; } } } } } // 带input的对话框; class ExtendsDialog extends Dialog{ constructor(options){ super(options); } createHtml(){ super.createHtml(); let myInput = document.createElement("input"); myInput.type = "text"; myInput.classList.add("input-inner"); this.div.querySelector(".k-body").appendChild(myInput); } sure(){ let value = this.div.querySelector(".input-inner").value; console.log(value); super.sure(value);//1.子类传给父类 } } // 自定义组件 class ShowDialog extends HTMLElement{ constructor(){ super(); // console.log(this); // 获取节点属性; let attr = this.attributes; let width = this.hasAttribute("width")?attr.width.value:"40%"; let height = this.hasAttribute("height")? attr.height.value:"250px"; let title = this.hasAttribute("title")?attr.title.value:"测试标题"; let content = this.hasAttribute("content")? attr.content.value:"内容"; // 注意布尔值: -> 获取到的值是一个字符串; let maskable = null; if(this.hasAttribute("maskable")){ maskable = attr.maskable.value; }else{ maskable = 'true'; } maskable = maskable==='true'?true:false; let dragable = null; if(this.hasAttribute("dragable")){ dragable = attr.dragable.value; }else{ dragable = 'true'; } dragable = dragable==='true'?true:false; let isCancel = null; if(this.hasAttribute("isCancel")){ isCancel = attr.isCancel.value; }else{ isCancel = 'false'; } isCancel = isCancel==='true'?true:false; /* 判断是否有这个值; 有就赋值; 三木判断是否等于 字符串'true' 将转为布尔值 */ let dialog = new Dialog({ width, height, title, content, dragable, maskable, isCancel }); this.innerHTML = `<button>${this.innerText}</button>`; this.onclick = function(){ dialog.open(); } } } customElements.define("show-dialog",ShowDialog);
成功一定有方法,失败一定有原因

浙公网安备 33010602011771号