技术开发 频道

探讨微软ASP.NET AJAX控件开发技术(客户端)


五、 其它几个重要的全局客户端方法    下列,我们列出在开发客户端控件时,一些常用(有些是必用的)的重要方法。
$get()
    这个方法是我们以前常用的Document.getElementById方法的一个快捷方式。此方法使用一个可选的父级DOM元素;如果没有指定这个父元素,那么,搜索操作将从Document对象开始执行。
$create()
    这个方法是Sys.Component.Create方法的一个快捷方式,用于实例化一个客户端组件,行为或控件。这个方法的完整定义如下所示:
$create(type, properties, events, references, element);

举例:
$create(AjaxImageButtonNamespace.MyCliImageButton, {'hoverImageUrl':'Images/updateh.gif'}, {'click':buttonClicked}, null, $get('cliBtn'));

    在此,第一个参数使用了对象的完整类型名。例如,当创建一个MyCliImageButton控件时,我们需要传递AjaxImageButtonNamespace.MyCliImageButton。这个参数必须存在。

    第二个参数对应一个键/值对(每一个一个键/值对对应一个特定属性及其该属性的取值)数组。例如,当创建MyCliImageButton控件时,我们需要要传递hoverImageUrl并给它赋值为{'hoverImageUrl':' Images/update-h.gif'}。如果我们想设置更多的属性,我们需要使用一个逗号来隔开这些键/值对。例如:
{'aProperty':value1, 'bProperty':value2}.

    第三个参数与第二个参数几乎相同。这个参数用于定义事件,也使用一个键/值对数组的表示方式。在上面的例子中,我们使用onButtonClick处理器订阅了click事件。

    第四个参数使用一个键/值对数组,用于引用那些在创建此组件时所需要使用的组件。既然本例中的图像按钮并没有请求任何对外部组件的引用;所以,我们简单地传递null为这个参数值。
第五个也即是最后一个参数是一个DOM元素。在创建行为和控件时,这是一个必需的参数;但是,对于一个非可视化组件而言,这个参数是可选的。

$find()
这个方法是Sys.Application.findComponent静态方法的快捷方式。其使用语法为:
var o = $find(id, [parent]);

    因此,它类似于$get方法;但是,它返回的是组件或其子类而不是DOM元素。可以给它指定一个可选的IContainer类型的父类,以便从它开始搜索。如果没有指定父类,那么,它从Sys._Application开始进行搜索。

    注】这里的parent既可以是Component也可以是Sys.UI.DomElement。当其类型为Component时,搜索对象被限定为它的子组件;当其类型为DOM元素时,搜索对象被限定为其下的子元素。
Function._validateParams
    我们知道,JavaScript并不是一个强类型化的语言;所以,为了充分保证方法中的参数符合既定的类型,必须进行大量编码,例如使用typeOf,parseInt,parseFloat,(parameters[0]!=null)等语句对参数进行测试。很可能是基于这样的原因,Ajax开发小组包括了这样一个功能极为强大的函数。现在,仅凭一个语句,这个函数就可以实现校验所有的方法参数。

    【注】虽然是一个函数,但它实际上是Function._validateParameterCount、Function._validateParameter及Function._validateParameterType等多个子函数的功能组合。读者可以参考下载源码中的MicrosoftAjax.js文件自行分析。
让我们来看一个简短的示例:
set_hoverImageUrl : function(value)
{
var e = Function._validateParams(arguments, [{name: 'value',
type: String, mayBeNull: false}]);
if (e) throw e;
//……
}

    在上面的示例中,我们要保证参数值是一个字符串数据类型并且非空。所以,这个函数的正确形式应该是:
Function._validateParams(params, expectedParams)
第一个参数是一个参数数组,通常是参数变量;第二个参数是一个定义了每一个参数信息的数组。每一个定义可以包含:
 Name:参数名;
 Type:参数的数据类型,例如String,Number,Boolean,Array或任何其它你自己创建的定制类型;
 mayBeNull:取值为true或false;缺省为false;
 optional:取值为true或false;缺省为false;
 parameterArray:取值为true或false;缺省为false;
 integer:取值为true或false;缺省为false;
 elementType:如果参数是一个数组,那么该项用于指定此数组包含的数据类型;
 elementInteger:如果参数是一个数组,那么该项用于确定此数组包含的是integer;
 elementDomElement:如果参数是一个数组,那么该项用于确定该数组包含的是DOM元素;
 elementMayBeNull:取值为true或false。如果参数是一个数组,那么该项用于确定是否该数组可以拥有任何的空项。
如果校验失败,Function._validateParams将返回一个应该由此函数的调用者抛出的异常。
$addHandler
    这是Sys.UI.DomEvent.addHandler的一个快捷方式。它提供了一种一致的方式用于“钩住”DOM元素的事件;同时,隐藏了不同浏览器下事件操作的复杂性。该方法的完整形式如下所示:
$addHandler(element, eventName, handler);
    第一个参数是一个DOM元素的引用。第二个参数相应于事件名(这里不必提供“on”前缀,ASP.NET Ajax系统为自动地添加这个前缀)。最后一个参数用于指定该事件的处理器函数。例如,在下列代码中,我为按钮“btnSelect”绑定了click事件(也即是为此按钮添加了一个事件代理,这与C#中的事件机制是基本一致的)。
$addHandler($get('btnSelect'), 'click', selectRowHandler);
//更多代码……
function selectRowHandler()
{
//处理click事件的代码
}
//更多代码……
$removeHandler
删除一个之前使用$addHandler创建的事件处理器。这个方法的语法形式与$addHandler完全一致。实际使用中,一般建议在pageUnload事件中删除所有的事件处理器。
$addHandlers
这个方法类似于$addHandler,其语法如下所示。
$addHandlers(element, events, [handlerOwner]);
因此,它允许使用单个语句指定相同DOM元素的多个事件代理。例如:
$addHandlers(this.get_element(), {'mouseover':this._mouseOverHandler,
'mouseout':this._mouseOutHandler, 'click': this._clickHandler}, this);
在上面的代码中,我们使用一个语句添加了mouseover,mouseout和click事件。第一个参数是对DOM元素的引用;第二个参数是一个“事件名/处理器”对数组。最后一个参数是一个可选的参数(通常是this)。
$clearHandlers
删除所有之前使用$addHandler或$addHandlers创建的事件处理器。它仅有一个参数(引用一个DOM元素)。例如,下列语句会清除所有添加到一个DOM元素上的事件处理器函数:
$clearHandlers(this.get_element());
Function.createDelegate
这是一个既能够“包装”一个现有函数,又能够返回一个新函数的函数。创建此函数的主要目的是解决this关键字的问题。在一个由一个DOM元素引发的事件处理器中,this关键字总是引用此DOM元素而不是类本身。这一点很重要,我们不妨来考虑下列的示例。如果我们如下面这样对图像按钮控件编程,那么,它将总是引发一个异常:
//…………
initialize : function()
{
//调用基类方法
AjaxImageButtonNamespace.MyCliImageButton.
callBaseMethod(this, 'initialize');
var target = this.get_element();
//添加需要使用的事件处理器
$addHandler(target, 'mouseover', this._onMouseOver);
},
//…………
_onMouseOver : function()
{
//请注意下面的this关键字,它不是MyCliImageButton控件本身,而是指相应的DOM元素,所以它肯定会引发一个异常
this.get_element().src = this._hoverImageUrl;
},
//……
接下来,让我们看一下真正有趣的Function.createDelegate函数。现在,我们按如下方式来重写前面的代码:
……
initialize : function()
{
//调用基类方法
AjaxImageButtonNamespace.MyCliImageButton.
callBaseMethod(this, 'initialize');
var target = this.get_element();
//请注意下面两句的联合使用
this._mouseOverHandler = Function.createDelegate(this, this._onMouseOver);
//添加需要的事件处理器
$addHandler(target, 'mouseover', this._mouseOverHandler);
},
……………
_onMouseOver : function(e) {
//现在的this关键字就变成了MyCliImageButton控件本身而不再是前面的DOM元素了。
//注意:现在e.target对应于原来的DOM元素
e.target.src = this._hoverImageUrl;
},
…………

    总之,Function.createDelegate方法要求使用指定两个参数。第一个参数是在该该事件处理器中的this所指向的对象。第二个参数是将作为事件处理器执行的函数。

Function.createCallback
    这个函数也有些特别;因为它也能够“包装”一个现有函数,同时返回一个新的函数。但是,创建这个函数的真正目的是为创建的回调函数提供相应的上下文数据(与Win32中的回调函数意义完全可比)。
Function.createCallback方法也要求使用两个参数。第一个参数是将被执行的函数,第二个参数指定相应的上下文数据。不同于Function.createDelegete,这个函数并没有解析this关键字。

    最后,除了上面的几个方法外,我还强力推荐你认真研究一下ASP.NETAJAX文档中提供的Sys.UI.DomEvent,Sys.UI.MouseButton和Sys.UI.Key等内容。

六、 总结
    在本篇中,我们讨论了开发Ajax控件所涉及的客户端相关技术并给出相应的示例。在下篇中,我们将着重讨论开发基于ASP.NET Ajax框架的控件所涉及的服务器端主要技术,也将一并开发出相应的示例程序。
0
相关文章