大家知道,jQuery里面的bind方法是用来绑定事件处理的,典型用法如下:

$('选择器').bind('事件类型',function(event){
    //这里是处理函数
});

在OAOP式系统中,需要大量的前台JS处理,这往往涉及到许多JS文件。限于性能考虑,不应该把所有相关的JS一次性加载过来。当然,解决办法有很多,在下在这里模仿bind的方式提供一种新的事件绑定处理脚本方式。初步设想是,将事件处理方法写入一个单独的脚本中,然后在事件触发时再去调用该脚本来实现事件处理。该插件的名称命名为bd,那么它的效果应该像这样:


$('选择器').bd('事件类型','JS脚本路径');





一个典型样例如下:



<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>测试页面</title>
<script type="text/javascript" src="../lib/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="../bd.js"></script>
<script type="text/javascript">
	$(function(){
		$('#t1').bd('click','handlers/h1.js',{p1:'这是传入的参数1'});
	});
</script>
</head>
<body>
	<a id="t1" href="#">点击显示传入参数</a>
</body>
</html>





而远程处理脚本handlers/h1.js的代码如下:



$.bd(function(event){
	alert(event.data.p1);
});




可以看到远程脚本除了用$.bd()包裹之外,里面的方法和bind方法的事件处理方法完全一致。


如果能组织好相关的处理脚本,那么完全可以将所有的业务处理代码组织到相关的远程处理脚本中,用目录来分类,使系统开发变得简单可靠。


这个想法已经实现,更多样例及实现代码参见附件。


插件源代码如下:



jQuery.extend({
	/**
	 * 用于注册事件处理方法,在JS文件中写入$.bd(function(event){//自己的业务代码,this指调用的元素,event是触发的事件}),就可以触发导入;
	 */
	bd : function(_h) {
		$(window).data('$.bd:h:' + $(window).data('$.bd:p:'), _h);// 注册方法
	}
});
jQuery.fn.extend({
	/**
	 * 根据事件触发执行相关的JS文件
	 * 
	 * @param type 事件类型
	 * @param data 事件参数
	 * @param url JS文件路径或者事件处理函数
	 */
	bd : function(type, url, data) {
		return $(this)._bd(type, url, data, true);
	},
	/**
	 * 根据事件触发执行相关的JS文件(仅一次)
	 * 
	 * @param type 事件类型
	 * @param data 事件参数
	 * @param url JS文件路径或者事件处理函数
	 */
	bd1 : function(type, url, data) {
		return $(this)._bd(type, url, data, false);
	},
	/**
	 * 根据事件触发执行相关的JS文件
	 * 
	 * @param type 事件类型
	 * @param data 事件参数
	 * @param url JS文件路径或者事件处理函数
	 * @param loop 是否循环执行标志位,false表示只执行一次
	 */
	_bd : function(type, url, data, loop) {
		var $this = $(this);
		var result = false;
		$.each([url,$(window).data('$.bd:h:' + url)],function(i,_h){
			if($.isFunction(_h)){
				if (loop) {
					result = $this.bind(type, data, _h);
				} else {
					result = $this.one(type, data, _h);
				}
			}
		});
		if(result){
			return result;
		}
		$(this).data('$.unbd:'+type,'');
		var _f = function(event){
			var $this = $(this);
			var data = event.data;
			if($this.data('$.unbd:'+data.type)===data.url){//已经取消绑定
				return;
			}
			var _h = $(window).data('$.bd:h:' + data.url);
			if(!$.isFunction(_h)){
				$(window).data('$.bd:p:', data.url);
				$.ajax({
					url : data.url,
					dataType : "script",
					async : false,
					success : function(){
						$this.data("$.bd:o:").unbind(data.type,_f);
					}
				});
				_h = $(window).data('$.bd:h:' + data.url);
			}
			if($.isFunction(_h)){
				if(data.loop){
					$this.data("$.bd:o:")._bd(data.type, data.url,data.data, data.loop);
				}
				$this["$.bd:_h"]=_h;
				event.data = data.data;
				event.handler = _h;
				return $this["$.bd:_h"](event);
			}
			return false;
		}

		return $this.data("$.bd:o:",$this).one(type,{
			type : type,
			data : data,
			url : url,
			loop : loop
		},_f);
	},
	/**
	 * 取消绑定
	 * 
	 * @param type 执行类型
	 * @param p JS文件路径或者事件处理函数
	 */
	unbd : function(type, p) {
		$(this).data('$.unbd:'+type,p);
		var h = $.isFunction(p)?p:$(window).data('$.bd:h:' + p);// 获取方法
		if($.isFunction(h)){
			$(this).unbind(type,h);
		}
		return $(this);
	}
});




注:附件中的样例不能直接在GOOGLE浏览器中运行,须放到服务器中,其它浏览器无此限制。


PS:注册之后苦等了三天,小弟首次发帖,希望多多鼓励支持:-)


PS2:做了一点调整,修正第一次加载时event.handler不正确的问题以及bd1执行两次的问题。


PS2:修正了取消绑定可能无效的问题,另外做了一些优化。


PS3:修正了取消绑定后恢复绑定无效的问题,增加了样例。