js也可以有自定义事件 注入就是这么爽
在c#中有delegate,还有特殊的可以直接应用于事件编程的delegate,那就是event。而在js中没有c#的event,更没有delegate,有的只是dom元素内置的的native的不可扩展的event,比如无法为input元素添加事件,只能在其拥有的事件(如onclick=handler)上扩展应用。那么能不能做到自定义的事件模拟效果呢?答案是肯定的,也就是本文的主题。
首先弄明白一下事件的意图——可以在发生一件事的时候执行额外的代码,如document.attachEvent('onclick', function(){alert('u click document')}),当点击页面时(事件发生了),就会执行我们为其挂接的其它代码(js中以function为语句集合,以下称为function),当然我们可以在一个事件上挂接任意多的function,这样就实现了一种灵活的可扩展编程接口。试想如果可以像在元素事件扩展应用一样可以在任意对象的任意方法上扩展,那对于js编程来讲就更加灵活了。先看一个例子,平时我们把相对对立的一个功能命名为一个function,并在需要的地方(通常是另一个function)调用以实现代码复用:
function F(){
this.method = function(){
alert('f.method is called')
g();
}
}
function g(){
alert(123)
}
var f = new F();
f.method()
我们把f.method中直接调用g改写一下,封装到一个Event对象中达到一样的效果,代码如下:
var Event = {
__list:[],
observe:function(obj, ev, fun){
this.__list.push({o:obj, e:ev, f:fun})
},
occor:function(obj, method){
var arr = []
for(var i=0; i<this.__list.length; i++){
if(this.__list[i].o==obj && this.__list[i].e==method) arr.push(this.__list[i]);
}
for(var i=0; i<arr.length; i++){
arr[i].f();
}
}
}
function F(){
this.method = function(){
alert('f.method is called')
Event.occor(this, 'method');
}
}
var f = new F();
Event.observe(f, 'method', function(){alert(123)})
f.method()
这样乍看上去好像费了“太多”功夫,但却把“在f中调用g的写法”更通用化了,如果要在f中调用h则只需要多些一行Event.occor(this, 'methodName'),写到这里你肯定也注意到methodName的写法和最开始的写法是一样的,都是硬编的不具灵活性,如果在每个类的方法中都写入Event.occor(this, 'method')就太不雅观了,也背离了我们的初衷,动态修改一下method把它加到最后一行就ok了,下一步就是解决它,改进代码如下:
var Event = {
__list:[],
observe:function(obj, ev, fun){
this.__list.push({o:obj, e:ev, f:fun})
},
occor:function(obj, method){
var arr = []
for(var i=0; i<this.__list.length; i++){
if(this.__list[i].o==obj && this.__list[i].e==method) arr.push(this.__list[i]);
}
for(var i=0; i<arr.length; i++){
arr[i].f();
}
},
inject:function(obj){
for(var p in obj){
obj[p] = new Function(obj[p].toString().replace('function(){', '').replace('}', 'Event.occor(this,p)'))
}
}
}
function F(){
this.method = function(){
alert('f.method is called')
}
}
var f = new F();
Event.inject(f);
Event.observe(f, 'method', function(){alert(123)})
f.method()
我们把显示的在被调用方法体内调用Event.occor改写到Event.inject中。到此我们就简单(还有一些安全代码没有处理,如没有判断obj[p]是否需要被改写、没有测试效率问题,没有处理更多添加Event.occor时的逻辑判断,下一步准备把它实现为一个Observeable对象,就更加灵活了)的完成了自定义事件。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 微信文章爬虫
- vue 随记(6):构建的艺术
- Centos7发布SpringBoot项目并后台运行
- k8s部署zookeeper集群
- dotnet 使用 SemaphoreSlim 可能的内存泄露
- WPF 绑定继承的样式提示 只能根据带有基类型 IFrameworkInputElement 的目标类型的 Style 样式
- 29.opengl高级光照-视差贴图
- SpringBoot集成Mybatis开启下划线格式的数据自动转换成小驼峰格式
- WPF 列表右键菜单比较符合 MVVM 的命令绑定方法
- Group Sample:一个简单有效的目标检测涨点Trick
- PyTorch版CenterNet数据加载解析
- WPF 使用 HandyControl 给 ListView 添加漂亮的表头效果
- kali2020 忘记密码
- 低比特量化之DoreFa-Net理论与实践
- 不用数组求多个数的最小值