asp.net ajax的事件机制小议
2007-05-10 11:12
405 查看
Asp.net Ajax提供的Sys.UI.DomEvent类,实现了跨浏览器的Dom事件操作,诸如以下几个常用的事件操作:$addHandler,$removeHandler,$addHandlers,$clearHandlers.
举一个简单的使用示例:
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>无标题页</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
<input id="Button1" type="button" value="button" />
<input id="txt1" type="text" />
</div>
</form>
</body>
</html>
<script type="text/javascript">
function pageLoad()
{
$addHandler(document,
4000
"click",function(e)
{
alert(e.clientX+":"+e.clientY);
});
$addHandler($get("Button1"),"click",function(e)
{
alert($get("txt1").value);
e.stopPropagation();
});
}
</script>
可以看见,通过$addHandler对一个DOM元素进行事件监听时,事件处理方法会传递进来一个默认的e参数,这一点和IE的全局的event对象的做法不同,而更符合标准的做法.
注意,这个e参数就是事件对象,而且是一个跨浏览器的事件对象,它具有如:target,clientX,clientY,keyCode,type...等常用的属性.
此外,这个DOM事件e对象,有两个比较重要的方法:preventDefault(阻止浏览器DOM元素的默认行为),stopPropagation(阻止DOM事件的冒泡传递).利用这两个方法,可以实现一些特别的需要.
其实绝大多数的Ajax库,都提供了这样的跨浏览器事件编程接口.但是,这些事件都只是"DOM事件"!我们监听一个DOM元素,在监听方法里写处理逻辑,这很简单也很正常.但是这个情况满足不了asp.net ajax组件对象系统的需要,它需要"对象级事件"的编码接口.
说到这里,必须提一下asp.net ajax的组件系统.和.net一样,asp.net ajax也引入了组件化编程的概念,它在扩展了javascript的一些功能和构建了一个完善的面向对象编程框架之外,另外构建了一个组件化编程的框架.这一点是asp.net ajax有别于其他ajax类库的一个最显著的地方,由于这一点,使得其他的类库像"游击队",而asp.net ajax更像"正规军".
所谓组件化,是说asp.net ajax提供了一个基础组件类:Sys.Component,由此基础组件类扩展而出:Sys.UI.Control,Sys.UI.Behavior,Sys.Preview.Action,AjaxControlToolkit.Animation.Animation等不同概念不同功能域的控件类,又从这些控件类,派生出整个asp.net ajax的所有组件类,实现整个系统的组件化编程...有点说远了,这里只谈事件...
组件是一个自给自足的类概念,它具有:属性,方法和事件.一个组件可以是DOM组件(如从Sys.UI.Control派生而来Sys.Preview.UI.Button),也可以是行为组件(如从Sys.UI.Behavior派生的Sys.Preview.ClickBehavior),还有可能是动画组件(如从AjaxControlToolkit.Animation.Animation派生的AjaxControlToolkit.Animation.ParentAnimation)等等.
所谓"事件",逻辑描述就是:由一个"触因",引发一个操作.
从这点讲,一般意义的"DOM事件",不过就是天然支持了一个html dom的事件系统,这个DOM事件系统,可以看作是一个"触因",我们实现"对象级事件",需要的不过是另外的一种"触因"罢了.下面我例举一个简单的示例,看看怎么在自定义的类之中实现"对象级事件":
<script type="text/javascript">
var MyClass = function(name)
{
this._name = name;
this._nameChangedHandler = new Array();//事件处理器集合
}
function MyClass$set_name(value)
{//当你执行set_name方法时,set_name方法就是一个"触因".
if(this._name != value)
{
this._name = value;
this._onNameChanged();//这个方法的调用,是实现自定义事件的根本.
}
}
function MyClass$get_name()
{
return this._name;
}
//加入name属性变化监听方法
function MyClass$add_nameChanged(handler)
{
Array.add(this._nameChangedHandler,handler);
}
//移除name属性变化监听方法
function MyClass$remove_nameChanged(handler)
{
Arr
dd07
ay.remove(this._nameChangedHandler,handler);
}
//实现name属性变化监听自事件
function MyClass$_onNameChanged()
{
var sf = this;
Array.forEach(this._nameChangedHandler,function(v,i,array)
{
v(sf,"nameChanged");//最主要的技术实现是这行代码,其实是监听方法的循环调用,"激发"了监听方法!
});
}
MyClass.prototype =
{
_name: null,
_nameChangedHandler: null,
set_name: MyClass$set_name,
get_name: MyClass$get_name,
_onNameChanged: MyClass$_onNameChanged,
add_nameChanged: MyClass$add_nameChanged,
remove_nameChanged: MyClass$remove_nameChanged
}
//监听方法1
function Fuc(sender,eventargs)
{
//我们在事件监听方法中做一些事
alert(sender.get_name()+":"+eventargs);
}
//监听方法2
function Fuc2(sender,eventargs)
{
alert(sender.get_name());
}
//创建自定义类的对象实例
var a = new MyClass("fanrong");
//加入"name属性变化事件"的监听方法
a.add_nameChanged(Fuc);
a.add_nameChanged(Fuc2);
//改变下姓名属性,会激发nameChanged事件
a.set_name("chunrong");
</script>
大家可以看到,在这个示例中,我们没有使用任何的DOM事件,但确实是演示了一个事件的监听方法的绑定和激发.
这里揭示了3点实现自定义事件的根本原理:
1)事件监听方法,是使用一个集合来存放的.这里使用的是数组.通过数组元素的增/删,实现事件监听方法的绑定和移除;
2)"激发"事件,其实就是遍历集合中的监听方法,依次加以调用,调用的时候传入事件参数;
3)属性值变化事件激发的"触因",其实现的原理是"索引器"内部的_onXXX方法的调用,如果没有set_XXX这样的属性索引器,至少"属性值变化事件"是实现不了的,因为我们需要在改变属性值的时候,有地方给我们写调用_onXXX这样"激发"事件的代码 :)
这个例子虽然小,但它是asp.net ajax中,整个组件系统实现"事件"的根本原理.一般,通过Sys.UI.Control派生的组件类,它们事件的"触因"是天然就有的DOM事件,而其他的组件类,实现事件的"触因"是各种各样的,但总有一个"点"是进行了"_onXXX"这样的事件激发方法的调用.
从这些基本原理出发,微软提供了一个Sys.EventHandlerList类,如果查看它内部的代码,可以发现它提供了一个"事件对象"集合(是一个Object对象),每一个"事件对象"通过"事件名称"对应一个数组,这个数组就是"事件监听方法集合",这一点和我上面举的例子的做法是一样的.只是Sys.EventHandlerList可以为所有的事件绑定和移除对应的事件监听方法,而我举的例子里,只是简单的说明了如何为一个事件实现事件监听方法的绑定/移除和激发.
此外,Sys.EventHandlerList并没有做"事件激发"的工作.因为"激发"事件时,需要传递具体的参数,而每一个不同的类,都有自己不同的参数需要传递,显然,这个步骤不通用,因此不能封装在Sys.EventHandlerList内中,而应该在具体编写一个类的激发事件代码时,由类开发程序员自己决定传递什么参数.
举一个简单的使用示例:
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>无标题页</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
<input id="Button1" type="button" value="button" />
<input id="txt1" type="text" />
</div>
</form>
</body>
</html>
<script type="text/javascript">
function pageLoad()
{
$addHandler(document,
4000
"click",function(e)
{
alert(e.clientX+":"+e.clientY);
});
$addHandler($get("Button1"),"click",function(e)
{
alert($get("txt1").value);
e.stopPropagation();
});
}
</script>
可以看见,通过$addHandler对一个DOM元素进行事件监听时,事件处理方法会传递进来一个默认的e参数,这一点和IE的全局的event对象的做法不同,而更符合标准的做法.
注意,这个e参数就是事件对象,而且是一个跨浏览器的事件对象,它具有如:target,clientX,clientY,keyCode,type...等常用的属性.
此外,这个DOM事件e对象,有两个比较重要的方法:preventDefault(阻止浏览器DOM元素的默认行为),stopPropagation(阻止DOM事件的冒泡传递).利用这两个方法,可以实现一些特别的需要.
其实绝大多数的Ajax库,都提供了这样的跨浏览器事件编程接口.但是,这些事件都只是"DOM事件"!我们监听一个DOM元素,在监听方法里写处理逻辑,这很简单也很正常.但是这个情况满足不了asp.net ajax组件对象系统的需要,它需要"对象级事件"的编码接口.
说到这里,必须提一下asp.net ajax的组件系统.和.net一样,asp.net ajax也引入了组件化编程的概念,它在扩展了javascript的一些功能和构建了一个完善的面向对象编程框架之外,另外构建了一个组件化编程的框架.这一点是asp.net ajax有别于其他ajax类库的一个最显著的地方,由于这一点,使得其他的类库像"游击队",而asp.net ajax更像"正规军".
所谓组件化,是说asp.net ajax提供了一个基础组件类:Sys.Component,由此基础组件类扩展而出:Sys.UI.Control,Sys.UI.Behavior,Sys.Preview.Action,AjaxControlToolkit.Animation.Animation等不同概念不同功能域的控件类,又从这些控件类,派生出整个asp.net ajax的所有组件类,实现整个系统的组件化编程...有点说远了,这里只谈事件...
组件是一个自给自足的类概念,它具有:属性,方法和事件.一个组件可以是DOM组件(如从Sys.UI.Control派生而来Sys.Preview.UI.Button),也可以是行为组件(如从Sys.UI.Behavior派生的Sys.Preview.ClickBehavior),还有可能是动画组件(如从AjaxControlToolkit.Animation.Animation派生的AjaxControlToolkit.Animation.ParentAnimation)等等.
所谓"事件",逻辑描述就是:由一个"触因",引发一个操作.
从这点讲,一般意义的"DOM事件",不过就是天然支持了一个html dom的事件系统,这个DOM事件系统,可以看作是一个"触因",我们实现"对象级事件",需要的不过是另外的一种"触因"罢了.下面我例举一个简单的示例,看看怎么在自定义的类之中实现"对象级事件":
<script type="text/javascript">
var MyClass = function(name)
{
this._name = name;
this._nameChangedHandler = new Array();//事件处理器集合
}
function MyClass$set_name(value)
{//当你执行set_name方法时,set_name方法就是一个"触因".
if(this._name != value)
{
this._name = value;
this._onNameChanged();//这个方法的调用,是实现自定义事件的根本.
}
}
function MyClass$get_name()
{
return this._name;
}
//加入name属性变化监听方法
function MyClass$add_nameChanged(handler)
{
Array.add(this._nameChangedHandler,handler);
}
//移除name属性变化监听方法
function MyClass$remove_nameChanged(handler)
{
Arr
dd07
ay.remove(this._nameChangedHandler,handler);
}
//实现name属性变化监听自事件
function MyClass$_onNameChanged()
{
var sf = this;
Array.forEach(this._nameChangedHandler,function(v,i,array)
{
v(sf,"nameChanged");//最主要的技术实现是这行代码,其实是监听方法的循环调用,"激发"了监听方法!
});
}
MyClass.prototype =
{
_name: null,
_nameChangedHandler: null,
set_name: MyClass$set_name,
get_name: MyClass$get_name,
_onNameChanged: MyClass$_onNameChanged,
add_nameChanged: MyClass$add_nameChanged,
remove_nameChanged: MyClass$remove_nameChanged
}
//监听方法1
function Fuc(sender,eventargs)
{
//我们在事件监听方法中做一些事
alert(sender.get_name()+":"+eventargs);
}
//监听方法2
function Fuc2(sender,eventargs)
{
alert(sender.get_name());
}
//创建自定义类的对象实例
var a = new MyClass("fanrong");
//加入"name属性变化事件"的监听方法
a.add_nameChanged(Fuc);
a.add_nameChanged(Fuc2);
//改变下姓名属性,会激发nameChanged事件
a.set_name("chunrong");
</script>
大家可以看到,在这个示例中,我们没有使用任何的DOM事件,但确实是演示了一个事件的监听方法的绑定和激发.
这里揭示了3点实现自定义事件的根本原理:
1)事件监听方法,是使用一个集合来存放的.这里使用的是数组.通过数组元素的增/删,实现事件监听方法的绑定和移除;
2)"激发"事件,其实就是遍历集合中的监听方法,依次加以调用,调用的时候传入事件参数;
3)属性值变化事件激发的"触因",其实现的原理是"索引器"内部的_onXXX方法的调用,如果没有set_XXX这样的属性索引器,至少"属性值变化事件"是实现不了的,因为我们需要在改变属性值的时候,有地方给我们写调用_onXXX这样"激发"事件的代码 :)
这个例子虽然小,但它是asp.net ajax中,整个组件系统实现"事件"的根本原理.一般,通过Sys.UI.Control派生的组件类,它们事件的"触因"是天然就有的DOM事件,而其他的组件类,实现事件的"触因"是各种各样的,但总有一个"点"是进行了"_onXXX"这样的事件激发方法的调用.
从这些基本原理出发,微软提供了一个Sys.EventHandlerList类,如果查看它内部的代码,可以发现它提供了一个"事件对象"集合(是一个Object对象),每一个"事件对象"通过"事件名称"对应一个数组,这个数组就是"事件监听方法集合",这一点和我上面举的例子的做法是一样的.只是Sys.EventHandlerList可以为所有的事件绑定和移除对应的事件监听方法,而我举的例子里,只是简单的说明了如何为一个事件实现事件监听方法的绑定/移除和激发.
此外,Sys.EventHandlerList并没有做"事件激发"的工作.因为"激发"事件时,需要传递具体的参数,而每一个不同的类,都有自己不同的参数需要传递,显然,这个步骤不通用,因此不能封装在Sys.EventHandlerList内中,而应该在具体编写一个类的激发事件代码时,由类开发程序员自己决定传递什么参数.
相关文章推荐
- asp.net Application_AcquireRequestState事件,导致Ajax客户端不能加载
- ASP.NET:为 AJAX 请求添加客户端事件
- Asp.net Ajax 客户端页面生命周期原生事件
- ★★★【庖丁解牛:纵向切入Asp.net 3.5控件和组件开发技术系列—(5)事件和数据回发机制】★★★
- 使用ASP.NET AJAX开发服务器端事件通知器
- ASP.NET:为 AJAX 请求添加客户端事件
- 添加/删除请求开始事件的方法 (asp.net ajax框架)
- ASP.NET中的事件冒泡机制
- Asp.Net+Jquery.Ajax详解7-全局Ajax事件
- Asp.net 更改Alert样式和后台注册Jquery的Ajax异步提交事件[包括处理前操作、处理后操作(注明:此方法只是作为参考,如有需要可自行修改)]
- asp.net事件回传机制
- ASP.NET AJAX 添加请求处理事件来防止按钮重复提交
- Asp.Net ajax 面向对象类型系统2 - 使用事件
- asp.net ajax 客户端事件浏览器,ASP.NET AJAX: Client-side event viewer
- ASP.NET事件回传机制
- ASP.NET:为 AJAX 请求添加客户端事件
- Asp.Net+Jquery.Ajax详解7-全局Ajax事件
- ASP.NET事件回传机制
- ASP.NET 事件(回传)机制
- Asp.net Ajax 的 PageRequestManager类的事件