当前位置: 代码迷 >> 综合 >> 面向对象三
  详细解决方案

面向对象三

热度:44   发布时间:2023-10-01 01:06:02.0

目录

1.组件样式模块化

2.自定义事件

2.1方法一:使用ES5实现

2.2方法二:使用ES6实现

3.组件模块化开发——使用自定义事件实现第二个对话框有input输入框

4.系统预定义事件(EventTarget)

5.组件模块化开发——使用系统预定义事件(EventTarget)

6.EventTarget使用CostomEvent实现获取回调结果

7.使用EventTarget的CustomEvent实现获取input输入框的输入值


1.组件样式模块化

组件样式模块化:把组件、视图、JS分别封装起来,使用时拿来即用。

组件:内部是独立的,外部是开放的(提供各种接口,API,配置)

示例:实现一个可设置是否拖拽,是否有遮罩层,是否有取消按钮,可设置宽高等基本配置的对话框(仿写Element-UI的对话框)。

步骤:

  1. 封装:通过class实现默认配置还是手动配置(Object.assign(a,b)对象合并:a,b分别为两个对象,对象a有值时,合并到第一个;没有值时,取b的值);
  2. 生成DOM结构(一定要返回this.dialogEle = dialogEle,才能在多次生成DOM结构后,找到对应的实例化后的对象上的dialog);
  3. CSS初始化时,dialog需要进行隐藏,点击时显示;
  4. 在实例化时,需要写对话框显示/隐藏(取消/确定/X都需要隐藏)方法,并通过用户操作实现对话框的显示/隐藏;
  5. 控制是否显示遮罩层,是否取消,是否可拖拽;
  6. 页面使用(new Dialog()),并设置显示对话框的配置内容;
  7. 使用事件委托,实现取消、确认,X三个功能;
  8. 实现拖拽功能;
  9. 确认和取消后回调;
  10. 使用ES6继承方式实现第二个对话框有input输入框,并且在点击确定后,可得到input的值

以下代码只实现了基本功能:生成对话框,可配置是否有遮罩层,可配置是否可取消,可拖拽,有回调。

CSS样式:必须导入,模块化的CSS

 .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%;display: none;}.k-wrapper {position: fixed;left: 0px;top: 0px;bottom: 0px;right: 0px;background: black;opacity: 0.4;z-index: 2000;display: none;}.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;}

JS文件:注意回调时,必须使用this.opts.cancel才能得到默认配置和手动配置合并后的结果

/*思路:封装;渲染视图;各种方法封装;事件委托实现方法封装;取消确定回调;自定义事件实现回调
*/
class Dialog {//传入的是调用对话框的自定义配置,当没有传入某些配置时,需要有默认配置constructor(options) {//使用Object.assign(a,b)方法将自定义配置和默认配置进行合并let newOptions = Object.assign({width: "40%",height: "250px",title: "默认标题",content: "默认内容",dragable: true, //是否可拖拽maskable: true, //是否有遮罩isCancel: true //是否有取消}, options);this.opts = newOptions;this.init();}//对话框显示方法:将对话框的k-wrapper和k-dialog样式设置为显示即可open() {//判断有遮罩层时k-wrapper才显示this.opts.maskable && (this.dialogEle.querySelector(".k-wrapper").style.display = "block");this.dialogEle.querySelector(".k-dialog").style.display = "block";}//取消,确定,X点击时关闭对话框close() {this.opts.maskable && (this.dialogEle.querySelector(".k-wrapper").style.display = "none");this.dialogEle.querySelector(".k-dialog").style.display = "none";}//取消时回调cancel() {console.log("点击取消了");}//确认时回调confirm() {console.log("点击确认了");}//组件初始化方法init() {this.renderDialog();//如果设置了可拖拽就调用this.opts.dragable && this.drag();//事件委托方法:当取消,确定,X点击时,关闭对话框this.dialogEle.addEventListener("click", e => {//注意:此处要使用箭头函数,this才会指向  实例化对象       switch (e.target.className) {case "k-close":this.opts.cancel();this.close();break;case "k-default":this.opts.cancel();this.close();break;case "k-primary":this.opts.confirm();this.close();break;}});}//渲染初始化对话框样式renderDialog() {let dialogEle = document.createElement("div");dialogEle.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>`;document.querySelector("body").appendChild(dialogEle);//将生成的dialog挂载在实例化后的对象上,使用时才能通过实例化获取对应某个对话框并进行处理this.dialogEle = dialogEle;}//拖拽:k-dialogdrag(){let dialog = this.dialogEle.querySelector(".k-dialog");dialog.addEventListener("mousedown",function(ev){let e = ev || window.event;let l = e.clientX - dialog.offsetLeft;let t = e.clientY - dialog.offsetTop;function move(e){let ev = e || window.event;dialog.style.left = ev.clientX - l + "px";dialog.style.top = ev.clientY - t + "px";}document.addEventListener("mouseover",move);document.addEventListener("mouseup",function(){document.removeEventListener("mouseover",move);},{once:true});e.preventDefault();});}
}

页面文件:

<!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"><link rel="stylesheet" href="dialog.css"><title>Document</title>
</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="showDailog">点击</button><script src="dialog.js"></script><script>{//需求:自定义组件模块化开发/*思路:封装;渲染视图;各种方法封装;事件委托实现方法封装;取消确定回调;自定义事件实现回调*///使用:点击按钮时显示对话框let dialog = new Dialog({width: "30%",height: "200px",// title: "配置标题",// content: "配置内容",dragable: true, //是否可拖拽maskable: true, //是否有遮罩isCancel: true, //是否有取消//取消回调cancel(){console.log("cancel");},//确认回调confirm(){console.log("confirm");}});let showDailog = document.querySelector(".showDailog");showDailog.addEventListener("click", function () {dialog.open();});}</script>
</body>

2.自定义事件

目的:把函数当做事件执行。可以一次点击或触发,执行多个函数。ES6中有自定义的时间API(EventTarget)。

思路:

  1. 添加事件,把所有的函数存在数组对象里;
  2. 触发事件,如果存在就执行这个事件函数;
  3. 移除事件,判断这个事件在对象的数组里存在就splice删除

两种方法实现:ES5和ES6

注意点:移除事件时,判断事件是否存在在数组中(!fn in this.eventObj[eventName]),和删除指定事件时的判断方式(this.eventObj[eventName][i] === fn)。

2.1方法一:使用ES5实现

分析:

  • 如果不写自定义事件,多个事件需要调用多次执行;
  • 使用事件监听方法addEventListener()也可以实现一次触发多次执行;
  • 使用自定义事件实现一次触发,执行多个事件;
<!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>
</head>
<button>点击</button><body><script>{//需求:自定义事件,一次触发执行多个事件let btn = document.querySelector("button");function event1() {console.log("event1...");}function event2() {console.log("event2...");}function event3() {console.log("event3...");}//1.按照原始写法,多个事件执行需要进行分别调用// event1();// event2();//2.事件监听,本来就可以实现一次触发执行多个事件// btn.addEventListener("click",event1);// btn.addEventListener("click",event2);//3.自定义事件:实现一次触发执行多个事件//原理:先将多个事件存放在对象的数组里,当触发时循环执行对象的数组里的事件;需要移出事件时,也可以循环找到对应事件进行移出let eventObj = {// event:[event1,event2]};//添加事件:将所有事件存到数组中function addEvent(eventName, fn) {//如果typeof event[eventName]为undefined证明数组中方法不存在if (typeof eventObj[eventName] == "undefined") {eventObj[eventName] = [];}eventObj[eventName].push(fn);}//事件触发function triggerEvent(eventName) {if (typeof eventObj[eventName] == "undefined") {return;}eventObj[eventName].forEach(item => {item();});}//移出事件function removeEvent(eventName, fn) {//判断事件不存在就不移出if (!fn in eventObj[eventName]) {return;}//循环数组eventObj[eventName],如果数组中有方法为fn的就删除for (let i = 0; i < eventObj[eventName].length; i++) {//保证删除的是指定的事件if (eventObj[eventName][i] === fn) {eventObj[eventName].splice(i, 1);//删除了就不再继续循环break;}}}btn.addEventListener("click",function(){addEvent("event", event1);addEvent("event", event2);removeEvent("event", event2);triggerEvent("event");});}</script>
</body></html>

2.2方法二:使用ES6实现

分析:基本思路和ES5一样,只是写法不同

<!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>
</head>
<button>点击</button><body><script>{//需求:自定义事件,class实现class Event {constructor() {this.eventObj = {// event:[event1,event2]};}//将所有事件存到数组中addEvent(eventName, fn) {//如果typeof event[eventName]为undefined证明数组中方法不存在if (typeof this.eventObj[eventName] == "undefined") {this.eventObj[eventName] = [];}this.eventObj[eventName].push(fn);}//事件触发triggerEvent(eventName) {if (typeof this.eventObj[eventName] == "undefined") {return;}this.eventObj[eventName].forEach(item => {item();});}//移出事件removeEvent(eventName, fn) {//判断事件不存在就不移出if (!fn in this.eventObj[eventName]) {return;}//循环数组eventObj[eventName],如果数组中有方法为fn的就删除for (let i = 0; i < this.eventObj[eventName].length; i++) {//保证删除的是指定的事件if (this.eventObj[eventName][i] === fn) {this.eventObj[eventName].splice(i, 1);//删除了就不再继续循环break;}}}}function event1() {console.log("event1...");}function event2() {console.log("event2...");}function event3() {console.log("event3...");}let e = new Event();e.addEvent("event", event1);e.addEvent("event", event2);e.addEvent("event", event3);e.removeEvent("event", event2);e.triggerEvent(event1);}</script>
</body></html>

3.组件模块化开发——使用自定义事件实现第二个对话框有input输入框

Dialog继承自定义事件类Event,input输入框子类继承父类Dialog;

注意:添加函数到事件中时,必须使用this.opts.cancel,不能直接使用this.cancel,这样不会实现手动配置和默认配置的属性和方法合并

Html文件:

<!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"><link rel="stylesheet" href="dialog.css"><title>Document</title>
</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="showDailog">点击</button><button class="inputDailog">点击</button><script src="dialog-myEvent.js"></script><script>{//需求:自定义组件模块化开发/*思路:封装;渲染视图;各种方法封装;事件委托实现方法封装;取消确定回调;自定义事件实现回调*///使用:点击按钮时显示对话框let dialog = new Dialog({width: "40%",height: "250px",title: "配置标题",content: "配置内容",dragable: true, //是否可拖拽maskable: true, //是否有遮罩isCancel: true, //是否有取消//取消回调cancel(){console.log("cancel");},//确认回调confirm(e){console.log("confirm",e);}});let showDailog = document.querySelector(".showDailog");showDailog.addEventListener("click", function () {dialog.open();});//有输入框的对话框let msgDialog = new InputDialog({width: "40%",height: "250px",title: "配置标题",content: "配置内容",dragable: true, //是否可拖拽maskable: true, //是否有遮罩isCancel: true, //是否有取消//取消回调cancel(){console.log("cancel");},//确认回调confirm(){console.log("confirm");}});let inputDailog = document.querySelector(".inputDailog");inputDailog.addEventListener("click", function () {msgDialog.open();});}</script>
</body>

JS文件:

/*思路:封装;渲染视图;各种方法封装;事件委托实现方法封装;取消确定回调;自定义事件实现回调
*/
//需求:自定义事件,class实现
class Event {constructor() {this.eventObj = {// event:[event1,event2]};}//将所有事件存到数组中addEvent(eventName, fn) {//如果typeof event[eventName]为undefined证明数组中方法不存在if (typeof this.eventObj[eventName] == "undefined") {this.eventObj[eventName] = [];}this.eventObj[eventName].push(fn);}//事件触发triggerEvent(eventName) {if (typeof this.eventObj[eventName] == "undefined") {return;}this.eventObj[eventName].forEach(item => {item();});}//移出事件removeEvent(eventName, fn) {//判断事件不存在就不移出if (!fn in this.eventObj[eventName]) {return;}//循环数组eventObj[eventName],如果数组中有方法为fn的就删除for (let i = 0; i < this.eventObj[eventName].length; i++) {//保证删除的是指定的事件if (this.eventObj[eventName][i] === fn) {this.eventObj[eventName].splice(i, 1);//删除了就不再继续循环break;}}}
}
class Dialog extends Event {//传入的是调用对话框的自定义配置,当没有传入某些配置时,需要有默认配置constructor(options) {//使用Object.assign(a,b)方法将自定义配置和默认配置进行合并let newOptions = Object.assign({width: "40%",height: "250px",title: "默认标题",content: "默认内容",dragable: true, //是否可拖拽maskable: true, //是否有遮罩isCancel: true //是否有取消}, options);//继承某个类时,必须先调用super()再返回this,否则返回的this里没有父类的相关属性或方法super();this.opts = newOptions;this.init();}//对话框显示方法:将对话框的k-wrapper和k-dialog样式设置为显示即可open() {//判断有遮罩层时k-wrapper才显示this.opts.maskable && (this.dialogEle.querySelector(".k-wrapper").style.display = "block");this.dialogEle.querySelector(".k-dialog").style.display = "block";}//取消,确定,X点击时关闭对话框close() {this.opts.maskable && (this.dialogEle.querySelector(".k-wrapper").style.display = "none");this.dialogEle.querySelector(".k-dialog").style.display = "none";}//取消时回调cancel() {console.log("点击取消了");}//确认时回调confirm() {console.log("点击确认了");}//组件初始化方法init() {this.renderDialog();//如果设置了可拖拽就调用this.opts.dragable && this.drag();//把cancel和confirm加到自定义事件中(key不要一样,且不要再点击事件中设置)this.addEvent("cancel", this.opts.cancel);this.addEvent("confirm", this.opts.confirm);//事件委托方法:当取消,确定,X点击时,关闭对话框this.dialogEle.addEventListener("click", e => {//注意:此处要使用箭头函数,this才会指向  实例化对象       switch (e.target.className) {case "k-close":// this.cancel();this.triggerEvent("cancel");this.close();break;case "k-default":// this.cancel();this.triggerEvent("cancel");this.close();break;case "k-primary":// this.confirm();this.triggerEvent("confirm");this.close();break;}});}//渲染初始化对话框样式renderDialog() {let dialogEle = document.createElement("div");dialogEle.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>`;document.querySelector("body").appendChild(dialogEle);//将生成的dialog挂载在实例化后的对象上,使用时才能通过实例化获取对应某个对话框并进行处理this.dialogEle = dialogEle;}//拖拽:k-dialogdrag() {let dialog = this.dialogEle.querySelector(".k-dialog");dialog.addEventListener("mousedown", function (ev) {let e = ev || window.event;let l = e.clientX - dialog.offsetLeft;let t = e.clientY - dialog.offsetTop;function move(e) {let ev = e || window.event;dialog.style.left = ev.clientX - l + "px";dialog.style.top = ev.clientY - t + "px";e.preventDefault();}document.addEventListener("mouseover", move);document.addEventListener("mouseup", function () {document.removeEventListener("mouseover", move);}, {once: true});});}
}//有输入框的对话框
class InputDialog extends Dialog{constructor(options){super(options);this.renderInput();}renderInput(){//如果不可以点击是因为在鼠标按下设置了取消默认事件//渲染时,添加上文本框let kBody = this.dialogEle.querySelector(".k-body");let myinput = document.createElement("input");myinput.classList.add("input-inner");myinput.type = "text";kBody.appendChild(myinput);}}

4.系统预定义事件(EventTarget)

EventTarget是系统预定义的处理一次触发多次执行事件的方法。

使用时,

  1. 需要先创建事件:new Event();
  2. 添加事件ele.addEventListener('event', 事件);
  3. 触发事件:btn.dispatchEvent(event);
<!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>
</head>
<button>点击</button><body><script>{//需求:使用系统自定义类实现一次触发,执行多个事件function event1() {console.log("event1...");}function event2() {console.log("event2...");}function event3() {console.log("event3...");}var event = new Event('event');//创建一个event事件let btn = document.querySelector("button");btn.addEventListener('event', event1);//为元素绑定事件监听btn.addEventListener("event", event2);btn.addEventListener("event", event3);btn.onclick = function(){btn.dispatchEvent(event);//派发事件};}</script>
</body></html>

5.组件模块化开发——使用系统预定义事件(EventTarget)

HTML文件和自定义事件没有区别,只是引入的JS文件改变了

/*思路:封装;渲染视图;各种方法封装;事件委托实现方法封装;取消确定回调;自定义事件实现回调
*///需求:使用系统预定义事件
class Dialog extends EventTarget {//传入的是调用对话框的自定义配置,当没有传入某些配置时,需要有默认配置constructor(options) {//使用Object.assign(a,b)方法将自定义配置和默认配置进行合并let newOptions = Object.assign({width: "40%",height: "250px",title: "默认标题",content: "默认内容",dragable: true, //是否可拖拽maskable: true, //是否有遮罩isCancel: true //是否有取消}, options);//继承某个类时,必须先调用super()再返回this,否则返回的this里没有父类的相关属性或方法super();this.opts = newOptions;this.init();}//对话框显示方法:将对话框的k-wrapper和k-dialog样式设置为显示即可open() {//判断有遮罩层时k-wrapper才显示this.opts.maskable && (this.dialogEle.querySelector(".k-wrapper").style.display = "block");this.dialogEle.querySelector(".k-dialog").style.display = "block";}//取消,确定,X点击时关闭对话框close() {this.opts.maskable && (this.dialogEle.querySelector(".k-wrapper").style.display = "none");this.dialogEle.querySelector(".k-dialog").style.display = "none";}//取消时回调cancel() {console.log("点击取消了");}//确认时回调confirm() {console.log("点击确认了");}//组件初始化方法init() {this.renderDialog();//如果设置了可拖拽就调用this.opts.dragable && this.drag();//把cancel和confirm加到自定义事件中(key不要一样,且不要再点击事件中设置)// this.addEvent("cancel", this.cancel);// this.addEvent("confirm", this.confirm);//使用系统预定义事件处理var cancel = new Event('cancel');//创建并绑定一个event事件var confirm = new Event('confirm');//创建并绑定一个event事件this.addEventListener('cancel', this.opts.cancel);this.addEventListener('confirm', this.opts.confirm);//事件委托方法:当取消,确定,X点击时,关闭对话框this.dialogEle.addEventListener("click", e => {//注意:此处要使用箭头函数,this才会指向  实例化对象       switch (e.target.className) {case "k-close":// this.cancel();// this.triggerEvent("cancel");this.dispatchEvent(cancel);this.close();break;case "k-default":// this.cancel();// this.triggerEvent("cancel");this.dispatchEvent(cancel);this.close();break;case "k-primary":// this.confirm();// this.triggerEvent("confirm");this.dispatchEvent(confirm);this.close();break;}});}//渲染初始化对话框样式renderDialog() {let dialogEle = document.createElement("div");dialogEle.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>`;document.querySelector("body").appendChild(dialogEle);//将生成的dialog挂载在实例化后的对象上,使用时才能通过实例化获取对应某个对话框并进行处理this.dialogEle = dialogEle;}//拖拽:k-dialogdrag() {let dialog = this.dialogEle.querySelector(".k-dialog");dialog.addEventListener("mousedown", function (ev) {let e = ev || window.event;let l = e.clientX - dialog.offsetLeft;let t = e.clientY - dialog.offsetTop;function move(e) {let ev = e || window.event;dialog.style.left = ev.clientX - l + "px";dialog.style.top = ev.clientY - t + "px";e.preventDefault();}document.addEventListener("mouseover", move);document.addEventListener("mouseup", function () {document.removeEventListener("mouseover", move);}, {once: true});});}
}//有输入框的对话框
class InputDialog extends Dialog {constructor(options) {super(options);this.renderInput();}renderInput() {//如果不可以点击是因为在鼠标按下设置了取消默认事件//渲染时,添加上文本框let kBody = this.dialogEle.querySelector(".k-body");let myinput = document.createElement("input");myinput.classList.add("input-inner");myinput.type = "text";kBody.appendChild(myinput);}}

6.EventTarget使用CostomEvent实现获取回调结果

创建事件时不再使用new Event() 而是使用 new CustomEvent()

 //需求:使用CustomEvent获取事件回调// add an appropriate event listenerlet btn = document.querySelector("button");btn.addEventListener("cat", function (e) { console.log(e.detail) });// create and dispatch the eventlet event = new CustomEvent("cat", {detail: {hazcheeseburger: true}});btn.dispatchEvent(event);// Will return an object contaning the hazcheeseburger propertylet myDetail = event.detail;

7.使用EventTarget的CustomEvent实现获取input输入框的输入值

HTML文件:回调时使用e.detail得到回调值

 //确认回调confirm(e){console.log("手动配置 confirm",e.detail);},

完整HTML文件: 

<!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"><link rel="stylesheet" href="dialog.css"><title>Document</title>
</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="showDailog">点击</button><button class="inputDailog">点击</button><script src="dialog-EventTarget-CustomEvent.js"></script><script>{//需求:自定义组件模块化开发/*思路:封装;渲染视图;各种方法封装;事件委托实现方法封装;取消确定回调;自定义事件实现回调*///使用:点击按钮时显示对话框let dialog = new Dialog({width: "40%",height: "250px",title: "配置标题",content: "配置内容",dragable: true, //是否可拖拽maskable: true, //是否有遮罩isCancel: true, //是否有取消//取消回调cancel(){console.log("cancel");},//确认回调confirm(){console.log("confirm");}});let showDailog = document.querySelector(".showDailog");showDailog.addEventListener("click", function () {dialog.open();});//有输入框的对话框let msgDialog = new InputDialog({width: "40%",height: "250px",title: "配置标题",content: "配置内容",dragable: true, //是否可拖拽maskable: true, //是否有遮罩isCancel: true, //是否有取消//确认回调confirm(e){console.log("手动配置 confirm",e.detail);},//取消回调cancel(){console.log("手动配置 cancel");}});let inputDailog = document.querySelector(".inputDailog");inputDailog.addEventListener("click", function () {msgDialog.open();});}</script>
</body>

JS文件:

重要代码:

//使用CustomEvent获取事件回调ensure(inputVal){this.dispatchEvent(new CustomEvent("confirm",{detail:{inputVal}}));this.close();}

完整JS文件: 

/*思路:封装;渲染视图;各种方法封装;事件委托实现方法封装;取消确定回调;自定义事件实现回调
*/
//需求:使用CustomEvent获取input输入框的值
class Dialog extends EventTarget {//传入的是调用对话框的自定义配置,当没有传入某些配置时,需要有默认配置constructor(options) {//使用Object.assign(a,b)方法将自定义配置和默认配置进行合并let newOptions = Object.assign({width: "40%",height: "250px",title: "默认标题",content: "默认内容",dragable: true, //是否可拖拽maskable: true, //是否有遮罩isCancel: true,//是否有取消confirm(e) {console.log("默认配置点击了确定",e.detail);},cancel() {console.log("默认配置点击了取消");}}, options);//继承某个类时,必须先调用super()再返回this,否则返回的this里没有父类的相关属性或方法super();this.opts = newOptions;this.init();}//对话框显示方法:将对话框的k-wrapper和k-dialog样式设置为显示即可open() {//判断有遮罩层时k-wrapper才显示this.opts.maskable && (this.dialogEle.querySelector(".k-wrapper").style.display = "block");this.dialogEle.querySelector(".k-dialog").style.display = "block";}//取消,确定,X点击时关闭对话框close() {this.opts.maskable && (this.dialogEle.querySelector(".k-wrapper").style.display = "none");this.dialogEle.querySelector(".k-dialog").style.display = "none";}//取消时回调cancel() {console.log("点击取消了");}//确认时回调confirm() {console.log("点击确认了");}//组件初始化方法init() {this.renderDialog();//如果设置了可拖拽就调用this.opts.dragable && this.drag();//把cancel和confirm加到自定义事件中(key不要一样,且不要再点击事件中设置)// this.addEvent("cancel", this.cancel);// this.addEvent("confirm", this.confirm);//使用系统预定义事件处理let cancel = new Event('cancel');//创建并绑定一个event事件// var confirm = new Event('confirm');//使用CustomEvent回调时,在调用时设置this.addEventListener('cancel', this.opts.cancel);this.addEventListener('confirm', this.opts.confirm);//事件委托方法:当取消,确定,X点击时,关闭对话框this.dialogEle.addEventListener("click", e => {//注意:此处要使用箭头函数,this才会指向  实例化对象       switch (e.target.className) {case "k-close":// this.cancel();// this.triggerEvent("cancel");this.dispatchEvent(cancel);this.close();break;case "k-default":// this.cancel();// this.triggerEvent("cancel");this.dispatchEvent(cancel);this.close();break;case "k-primary":// this.confirm();// this.triggerEvent("confirm");// this.dispatchEvent(confirm);//通过CustomEvent获取回调this.ensure();// this.close();break;}});}//渲染初始化对话框样式renderDialog() {let dialogEle = document.createElement("div");dialogEle.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>`;document.querySelector("body").appendChild(dialogEle);//将生成的dialog挂载在实例化后的对象上,使用时才能通过实例化获取对应某个对话框并进行处理this.dialogEle = dialogEle;}//拖拽:k-dialogdrag() {let dialog = this.dialogEle.querySelector(".k-dialog");dialog.addEventListener("mousedown", function (ev) {let e = ev || window.event;let l = e.clientX - dialog.offsetLeft;let t = e.clientY - dialog.offsetTop;function move(e) {let ev = e || window.event;dialog.style.left = ev.clientX - l + "px";dialog.style.top = ev.clientY - t + "px";e.preventDefault();}document.addEventListener("mouseover", move);document.addEventListener("mouseup", function () {document.removeEventListener("mouseover", move);}, {once: true});});}//使用CustomEvent获取事件回调ensure(inputVal){this.dispatchEvent(new CustomEvent("confirm",{detail:{inputVal}}));this.close();}
}//有输入框的对话框
class InputDialog extends Dialog {constructor(options) {//写super时一定要把参数传进去,否则手动配置的没有效果super(options);this.renderInput();}renderInput() {//如果不可以点击是因为在鼠标按下设置了取消默认事件//渲染时,添加上文本框let kBody = this.dialogEle.querySelector(".k-body");let myinput = document.createElement("input");myinput.classList.add("input-inner");myinput.type = "text";kBody.appendChild(myinput);}//使用CustomEvent获取事件回调ensure(){let inputVal =  this.dialogEle.querySelector(".input-inner").value;super.ensure(inputVal);}
}