首页 > javascript > js项目中的事件通讯。

js项目中的事件通讯。

2010年9月19日 effect 发表评论 阅读评论

说明:本文是对文章:http://web302.com/2010/08/js-function-of-several-useful/的补充

很多的web应用都是基于事件驱动的,比如tab切换。有两个选项卡,通过click或者mouseover事件来驱动展现情况。类似这种应用场景数不胜数。像这种应用是给dom对象绑定click事件就可以完成,非常之简便。

像上面那个例子,就是典型的事件驱动的应用场景。现在有个社区型的应用场景:有一个用户中心页面,首先从服务器拉取用户的个人信息,然后再根据用户的信息分表去拉取用户的好友列表,站内信个数等信息。

常规处理:

这个很简单,异步拉取用户信息,拉取成功之后就分别执行对应的方法,如拉取好友列表,拉取站内信个数等。下面贴下伪代码:

ajax('/getuser?uid=123',function(response){
    loadFriend(response);//拉取好友列表
    loadMsgNum(response);//拉取消息个数
    ...............
});

这个处理方式没有任何问题。现在假设某台需求有变更,还要拉取用户的动态信息,现在是不是又要更改这个回调,加上loadDt(response)。假设需求又有变动,拉取好友从loadFriend函数改为loadFriendTwo()。想象一下,如果处理好友列表和拉取个人信息的模块不是同一个职员在处理,那么每次改动都要涉及到两个人的改动,也许更多。而且两者之间的耦合性也是非常之强的!有没有更好的处理方式吗?

现在回到本文开头提到的事件处理。如果有个DOM,当用户点击这个DOM之后,A同事要处理一些事情,B同事也要处理一些事情。那么很自然的A同事监听这个DOM的CLICK事件,B同事也是可以注册自己的事件监听,这样是不是没有任何的耦合?

事件处理:

这样我们就可以用事件的方式来处理这个应用场景,让各个模块注册自己的监听回调,等拉取个人信息成功之后就触发这个事件。下面看第二种方式的伪代码:

function user(uid){
   this.uid=uid;
}
event(user,EventSource);//让user继承EventSource。
user.prototype.load=function(){
         var that=this;
         ajax("/getuser?uid="+this.uid,function(response){
                  that.fireEvent('onUserReady',response);
         });
}
 
var userObj=new user(123);
 
//加载好友模块开始
userObj.addEventListener(userObj,'onUserReady',loadFriend);
function loadFriend(that,event,response){
 
}
//加载好友模块结束
 
 
//加载消息个数模块
userObj.addEventListener(userObj,'onUserReady',loadMsgNum);
function loadMsgNum(that,event,response){
 
}
//结束

如果以后有别的业务逻辑就继续增加监听而不是硬编码的回调,大大降低了耦合性。
下面给一个简单的事件监听和继承的DEMO:

var EventSource = function()
	{
	};
 
	EventSource.prototype.addEventListener = function(oListener, sEvent, fpNotify, tDelay)
	{
		if(!this[sEvent])		// !(sEvent in this)
			this[sEvent] = [ ];
		if(!(this[sEvent] instanceof Array))
			return false;
		for(var i=0; i<this[sEvent].length; i++)
			if(this[sEvent][i].o == oListener && this[sEvent][i].f == fpNotify)
				return true;
		this[sEvent].push( {o: oListener, f: fpNotify, t: tDelay} );
		return true;
	};
	EventSource.prototype.attachEvent = EventSource.prototype.addEventListener;
 
	// 解除事件绑定
	EventSource.prototype.removeEventListener = function(oListener, sEvent, fpNotify)
	{
		if(!this[sEvent] || !(this[sEvent] instanceof Array))
			return false;
		for(var i=0; i<this[sEvent].length; i++)
			if(this[sEvent][i].o == oListener && this[sEvent][i].f == fpNotify) {
				this[sEvent].splice(i, 1);
				if(0 == this[sEvent].length)
					delete this[sEvent];
				return true;
			}
		return false;
	};
	EventSource.prototype.detachEvent = EventSource.prototype.removeEventListener;
 
	// 激发事件
	EventSource.prototype.dispatchEvent = function(sEvent)
	{	
		if(!this[sEvent] || !(this[sEvent] instanceof Array))
			return false;
		var args = [this].concat( argumentsToArray (arguments) );
		var listener = this[sEvent].slice(0);
		for(var i=0; i<listener.length; i++)
			if(typeof(listener[i].t) == "number")
				listener[i].f.delayApply( listener[i].t, listener[i].o, args );
			else
				listener[i].f.apply( listener[i].o, args );
		return true;
	};
	EventSource.prototype.fireEvent = EventSource.prototype.dispatchEvent;
 
	function argumentsToArray(args)
	{
		var result = [ ];
		for(var i=0; i<args.length; i++)
			result.push(args[i]);
		return result;
	};
 
	function extend(subClass,superClass){
		var F=function(){};
		F.prototype=superClass.prototype;
		subClass.prototype=new F();
		subClass.prototype.constructor=subClass;
		return subClass;
	}
 
	function fdemo(name){
		this.name=name;
	}
	extend(fdemo,EventSource);
 
 
	var subObj=new fdemo('yzm');
	subObj.addEventListener(subObj,'testEvent',function(that,event,a,b){
		alert('测试事件1'+a+b+that.name);
	});
	subObj.addEventListener(subObj,'testEvent',function(that,event,a,b){
		alert('测试事件2'+a+b+that.name);
	});
	subObj.fireEvent('testEvent','av','bv');
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.