开篇导读:在js中接触了内置的事件监听器,比如我们绑定了按钮的一个点击事件及赋予它一个事件处理函数,当点击按钮时便触发了这个内置监听器也就是onclick,于是开始执行我们赋予它的处理函数,由此我们会想到这种事件监听器我们自己可不可以定义呢?其实我们可以模拟内置事件的监听和触发过程,以此来达到我们需要的效果,在行业领域当中,它被称为观察者模式,直接上实现代码
//定义一个对象 let ObserverMode = { //定义添加自定义事件 on: function(){ // 判断参数是否满足条件,不满足则返回"参数错误" if(!arguments || arguments.length < 2) return this.warningMessages.info1; // 取到第一个参数作为自定义事件名 let observes = arguments[0]; // 判断第一个参数类型是否符合整数或字符串,不满足则返回"第一个参数不符合字符或数值类型" if(!this.isFistType(observes)) return this.warningMessages.info2; // 取到第二个参数作为自定义事件处理函数 let fn = arguments[1]; // 判断第二个参数类型,不满足则返回"第二个参数不是函数" if(!this.isSecondType(fn)) return this.warningMessages.info3; // 如果当前对象中不存在handler对象,也可以称为事件管理者,则创建对象 if(!this.handler) this.handler = {}; //如果事件管理者中不存在需要自定义事件的名称列表,则新建一个数组列表 if(!this.handler[observes]) this.handler[observes] = []; //在对应的自定义事件名称列表新增这个事件处理函数 this.handler[observes].push(fn); }, // 触发自定义事件 emit: function (){ // 取到事件名 let observes = arguments[0]; //取到参数 let params = arguments[1]; // 如果传入的事件名未注册或列表为空则返回"没有注册该事件" if(!this.handler[observes] || !this.handler[observes].length) return this.warningMessages.info4; //否则执行这个事件名称列表中的每个函数 else this.handler[observes].forEach(item =>{ item(params); }) }, // 移除自定义事件 off: function(){ // 判断参数是否满足条件,不满足则返回"参数错误" if(!arguments || !arguments.length) return this.warningMessages.info1; // 取到事件名 let observes = arguments[0]; //如果参数长度大于零和第一个参数不符合类型则返回"第一个参数不符合字符或数值类型" if(arguments.length > 0 && !this.isFistType(observes)) return this.warningMessages.info2; //如果参数长度等于1和事件管理者中存在该事件名称则移除对应列表,不满足则打印"没有注册该事件" if(arguments.length == 1){ if(Object.keys(this.handler).indexOf(observes) > -1){ delete this.handler[observes];return; } else return this.warningMessages.info4; } //取到参数 let fn = arguments[1]; //如果参数长度大于1和第二个参数不符合类型则返回"第二个参数不是函数" if(arguments.length > 1 && !this.isSecondType(fn)) return this.warningMessages.info3; else { // 判断事件列表中是否存在指定的事件处理函数 let index = this.handler[observes].indexOf(fn); //存在则移除对应的事件处理函数,否则打印"该事件列表没有找到对应的执行函数" index > -1?this.handler[observes].splice(index,1):console.log(this.warningMessages.info5); } }, // 判断第一个参数类型是否符合整数或字符串的方法 isFistType: function(value){ let type = typeof value; return (type == ‘number‘) || (type == ‘string‘); }, // 判断第二个参数类型 isSecondType: function(value){ return value.prototype && (value.__proto__ === Function.prototype) }, //提示数据 warningMessages: { info1: "参数错误", info2: "第一个参数不符合字符或数值类型", info3: "第二个参数不是函数", info4: "没有注册该事件", info5: "该事件列表没有找到对应的执行函数", } }
到此自定义的事件就实现了,上面代码的功能和内置事件不同的是,它需要我们手动调用对象中的emit触发,内置事件的每个事件名称只对应一个执行函数,这里的自定义事件是一个事件列表,可以同时处理多个同名事件函数
原文地址:https://www.cnblogs.com/denghaopositive/p/12678651.html
时间: 2024-10-11 18:21:31