扯扯javascript之自定义事件

如果您看到这篇文章 说明您知道js中事件这个东西,js中操作少不了事件的参与,小到click mouse等事件,大到面向对象处理事件。

白了,js就是一个处理事件的东东。。只是作用环境不同或者不明显而已。向上追溯祖宗八代 肯定能找到相关事件。。只是那个时代的js不像现在这么多功能,

在加上各个浏览器大哥之间怄气,可苦了我们这帮做js的小弟了。暂定一下 咱回来,别跑偏了。。。

自定义事件也是事件一种 跟函数绑定等一样,都是为了更完美的实现我们想要实现功能,达到code期望并且让代码读起来优美有含量。

这里所说的javascript自定义事件分为两种,一种是DOM自定义事件,另一种是js自定义事件。不过无论哪种自定义事件都是基于网上通常所说的观察者模式理论来实现。

所谓观察者模式,就是你作为观察者不去理会被观察者到底发生了什么,不过只要被观察者一旦出事了,你就要相应的做出决策,就像不去理会数据库里面的数据到底为什么更新了一样。那么为什么这样做呢。。。

好,我来回答你!

难不成你希望你写一个程序功能要考虑周全未来将要发生所有不可预测事情吗?

难不成你希望你封装了一段功能之后有人在里面乱七八糟的添加新功能吗?

就像你每天起床后都要考虑应该不应该起床呢?

good 貌似你服了这个反问。。。

怎么没人管管我呢 老跑偏。。

言归正传,先从DOM层的自定义事件说起,DOM自定义事件肯定是有别于浏览器自定义的事件,比如:click,mouse,key等事件,可以通过自定义进行添加,调用以及删除。

举个栗子吧:

前段时间我东家(产品)要求实现一个功能就是按下一个按钮去判断按下时间是否超过1秒才松开来处理两个不同事件。我心想这简单啊,去判断mouse事件的间隔时间不就完事了,于是咔嚓咔嚓写完了,东家一测很满意,然后说,

我还想知道用户到底按了多久,于是乎我就又咔嚓咔嚓咔嚓实现了,期间东家还过来说另外好几个地方都需要这功能,做完后帮他们支持一下。。

我立马爽快的答应了东家,心想不就是封装一个小组件么。回头一想这个组件里面处理事情不同,点击事件需求也不一定相同,关键的是我为啥还得多做那么多工作呢(不是工作态度问题哦。。)。。

突然 脑门一热,弄个自定义事件得了,谁不会用click事件呢?于是一个我的longPress事件横空出世了。主要代码如下,看完代码再说理论

function myLongPress(target, timeInterval) {

var timer;

var myEvt = document.createEvent('Event');

myEvt .initEvent('longPress', true, true);

target.addEventListener('mousedown', function() {

timer = Date.now();

}, false);

target.addEventListener('mouseup', function() {

if(Date.now() - timer > timeInterval) {

myEvt .interval= Date.now() - timer;

target.dispatchEvent(myEvt );

}

}, false);

}

myLongPress($('ni'), 2000);

$('ni').addEventListener('longPress', function(e) {

console.log('您已经摁下了 ' + e.duration + '毫秒了,走神了么.');
}, false);

主要根据dom中增加自定义事件的一个组合来实现我们功能(createEvent,initEvent,dispatchEvent),createEvent首先声明我要创建一个新的dom事件,于是initEvent接到通知开始定义了一个longPress事件,并且注入三个参数分别为 事件类型,是否冒泡,是否可取消。定义完之后我们就可以随意定义我们的longPress事件如何触发的了。我们在这个函数中传入两个值一个是操作元素,另一个是判断间隔自定义时间(就像我东家提的1秒),用我们的操作元素先去监听鼠标按下事件并且记录下按下那一刻的具体时间,然后让我们元素去监听鼠标抬起来时候的事件,这个时候我们的longPress事件才真正的定义完成,也就是说用户target做完这两个事件后自定义事件才会触发,就像click一样需要按下抬起来鼠标。于是我们去判断前两个事件间隔时间并将间隔时间作为一个事件属性供小伙伴们去调用,然后target开始去执行我们的自定义事件去了 也就是dispatchEvent。至此我们的自定义事件over了。怎么样简单不,你还可以随意的增加实例事件哦。

其实这就叫dom的自定义事件,怎么样 实现起来很简单吧,只是js中术语太多了 让我们以为多高深似的。。。

再说说另一种情况那就是js自定义事件

通常我们说的mvc结构层的view结构就是出于观察者身份,它只管检测数据有没有变化 如果变化我就要做什么,面向对象也有一个原则就是每个类都把重点放到一个功能上面尽可能降低耦合度,自定义事件使得观察者跟对象模块以及对象模块和对象模块之间划分了界限,大大提高了对象的复用性和程序的可维护性。自定义事件的实现原理也挺简单,平时我们定义的各种click事件其实就可以想象成把各种click事件放到一个{}里面,用到这个{}里面哪个事件时候哪个事件就出来工作,确定不用了再可以删除。同理我们可以想象一下我们如果自定义这种事件不也同样能达到这个效果么。于是开始动手:

首先我们定义个函数,并将之前说的那个{}至于里面作为公用属性。

var definedEvent=function(){

this.events={};

}

之后我们开始定义事件并且定义事件触发和删除机制:

definedEvent.prototype={

constructor:definedEvent,

addEvent:function(type,event){

if(typeof this.events[type]=='undefined'){
               
this.events[type]=new Array();
            }
            this.
events[type].push(event);

},

removeEvent:function(type,event){

if(this.events[type] instanceof Array){

var events=this.events[type];

for(var i=0,len=events.length;i<len;i++){

if(events[i]==event){

events.splice(i,1);

break;

}

}

}

},

fire:function(params){

if(!params.target){

params.target=this;

}

if(this.events[params.type] instanceof Array){

var events=this.events[params.type];

for(var i=0,len=events.length;i<len;i++){

events[i](params);

}

}

}

}

应用如下:

var a=new definedEvent();

function here(param){

alert("这是我自定义的方法"+param);

}

a.addEvent("myEvent",here)

a.fire({type:"myEvent",param:"myEvent"});

a.removeEvent('myEvent',here)

我们在函数基础上利用原型去增加其方法,首先在addEvent中增加并定义一个事件传两个参数一个是自定义事件名称type另一个是自定义具体事件event并且将其放到events这个公有属性中存储起来,然后在fire中进行引用,fire中传入一个参数params,params中的type是必须的 其type必须跟addEvent中的type是一致的才能触发,并且我们还可以在fire事件中params传参数从而达到触发事件目的。最后的最后如果我们想消除该自定义事件就直接removeEvent就ok了。

说到这里为止可能还会有人说 我干嘛自定义事件啊,我直接调用一个函数不就得了。。。,ok,我脾气好 不争辩,用事实举个栗子来说一下:

通常我们做前端都不可避免会遇到自定义弹出框功能,而且自定义的弹出框要根据业务去显示内容以及大小按钮等。一般来说我们都会将其封装为一个类,code人员只需要调用传参就可以了。但是实际业务中 很多都需要在弹出框下面遮住一层面纱防止在弹出框之外进行二次操作。 当然还有可能是打开或者关闭弹框时候实现其他功能。咱就拿这个最简单的举栗子!

那么这时候我们就有两个弹出框之外的事情去处理了,一个是打开弹出框时候要出现面纱在弹出框与页面之间,另一个是在点击关闭弹出框时候干掉面纱。这两个事件不可能写到我们已经写好的"类"中,那样会糟蹋了我们的类,并且以后维护起来特费劲。

打开时候好说,可以在调用弹出框类时候同步实现出现面纱,但是关闭时候呢?关闭按钮是在弹出框中的,并且关闭按钮默认功能只是将弹出框关闭。如何实现我们想要的干掉面纱呢。这个时候自定义事件就派上用场了!!!看代码

首先简单定义我们的弹出框类:

var myPop=function(id){

definedEvent.call(this);

this.id=id;

$(id).children[0].οnclick=function(){

that.close();//关闭按钮操作

}

}

myPop.prototype=new definedEvent();

myPop.prototype.show=function(){

/*弹出弹出框*/

}

myPop.prototype.close=function(){

/*关闭弹出框*/

this.fire('myClose')//触发自定义事件

}

function openPop(){

var pop=new myPop("id");

pop.addEvent("myClose",function(){

/*关闭面纱*/

})

pop.show()

}

上面代码我们用我们的弹出的类去继承自定义事件类(前面文章页说过了this以及继承的东东了)从而将this指向了myPop,同时myPop中也包含自定义事件的方法。这样一来我们就可以在我们的类中触发自定义事件,而自定义事件完全独立于我们的类之外,丝毫没有污染到原对象,这样就达到了我们代码可维护性,并且我们的弹出类是纯洁的了。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值