代码改变世界

从Atlas到Microsoft ASP.NET AJAX(5) - Higher-level Component Framework

2006-10-21 21:32 Jeffrey Zhao 阅读(...) 评论(...) 编辑 收藏
Higher-level Component Framework

高级组件的功能已经根据客户反馈,性能等诸多因素进行了修改。就以之前的Button为例,DomEvent类使用了一个基于标准的法提供了一套API用于DOM事件的分发。这个抽象能够良好运行在多个浏览器中。

许多API已经从CTP版本原来的地方(大都是Control类的成员)转移到了RTM版本中新的地方,而且被定义成了静态函数。这种做法减少了Contorl类的体积,而且这些操作DOM元素的API也能被开发人员随意使用了,不必像以前一样必须初始化一个Control对象。下面的示例展示了使用DomElement类的方式:
Sys.UI.DomElement.addCssClass($get('AddressLine1'), 'rqdFieldStyle');

请注意,在这里使用了新的$get函数,后面将对这些简写函数进行解释。

Component,Control and Behavior Class

在CTP版本中存在着以下三个类:ComponentControlBehavior。它们提供了许多重要的功能。其中ControlBehavior都是Component的子类。

这个模型在RTM版本中依旧存在。然而,经过了我们对它们用法的研究,并联系设计的原始目的进行研究后,改变了它们的使用方法。例如,在CTP版本中,一个Control类和一个DOM元素紧密联系了起来,您能通过Control对象来访问这个DOM元素。但是,尽管Behavior和DOM元素有直接的关系,我们却只能通过Control实例的一个Collection类型属性来访问到它。

RTM版本使DOM元素相关的工作变得更加灵活。ControlBehavior在概念上非常相似,都和一个DOM元素有这密切的关系。然而,现在它们已经相互独立了。

在RTM版本中,您能将一个Control实例与一个DOM元素联系起来,并且可以通过control来获得,这一点和CTP版本相同。另外,如果一个Behavior有一个Name属性,您也能通过这个名字从DOM元素中获得它。一个DOM元素可以有多个Bihavior与之相关联。下面的例子展示了如何使用RTM版本中新增的$create$get,通过一个DOM元素来得到它的Control对象和Behavior对象的引用。如下:
// Add a control and behavior to the GoShopping DOM element.
$create(Custom.UI.Button, {}, {'click':'myHandler'}, {}, $get('GoShopping'));
$create(Custom.UI.BorderBehavior, {'name':'border'}, {}, {}, $get('GoShopping'));

// Page developer accesses Button using the DOM element directly.
var gs = $get('GoShopping');
gs.control.set_text('Sale items');
gs.border.set_color('red');

// Page developer obtains the behavior using the $ separator.
var bb = $find(‘GoShopping$border);


Creating and Finding Components and Elements

在CTP版本中,您能够使用JavaScript来实例化一个对象,设置属性,并调用initialize方法。另外,您也可以使用XML-Script来操作它。在RTM版本的模型中:
  • 能够使用以前一样的方式使用Javascript操作组件。
  • 使用新的$create别名来操作组件。它的功能覆盖了实例化对象,设置属性,调用initialize方法等操作。这是一个强大的模型,也能被服务器控件所使用。
  • 使用Value-add包中的XML-Script支持,能够在RTM版本中使用与$create功能相同的操作。
  在RTM版本中,当一个组件使用$create初始化后,在全局的Application对象中会添加一个它的引用。页面开发人员能够使用新的别名来获得这些组件的引用,即使开发人员并没有对它进行初始化工作。例如,页面开发人员能够使用新的别名获得一个使用XML-Script初始化的组件。

$object, $find and $create Aliases

在CTP版本中,我们能够使用$object('GoShopping')来获得一个被XML-Script初始化的组件引用。Value-add包提供了这个操作。

在RTM版本的代码中,我们引入了$find方法。您能够使用这个方法来获得任意组件的引用——无论它是使用XML-Script还是$create初始化的。这意味着我们能够使用它来获得服务器端控件或Extender创造的对象,自然也包括使用JavaScript和XML-Script创造的对象。

Note:Beta版本中的$find方法能够通过ID来获得一个注册在Application中的组件,Behavior和控件。控件的ID和DOM元素的ID相同。而Behavior能够通过它所在的元素ID和它的类名得到一个默认的UniqueID(“elementId$ClassName”)——例如AddressLine1$AutoCompleteBehavior。

Comment  我对这里的说法做一些补充。虽然Behavior会获得一个默认的UniqueID,但是如果一个控件里同时存在两个相同的Behavior会出现什么情况呢?如果同时存在两个不同的,但是名称相同(所在namespace不同)的Behavior,又会如何呢?只有尝试了或者分析代码之后才能知道。因此最好还是为每个需要find到的Behavior提供一个名字。这样就能像之前的例子一样,通过$find('GoShopping$border')来获得。

$ and $get

在CTP版本中定义了一个全局的$()来提供document.getElementById()的功能。但是无论是RTM版本还是Value-add包已经取消了对它的支持。这么做的原因是为了避免与其他使用$()的AJAX类库产生冲突。在RTM版本中提供了$get函数来替代原有的$()函数,它们具有完全相同的功能。

$addHandler and $removeHandler

RTM版本提供的$addHandler$removeHandler操作提供了一个简单的方式创建和移出对DOM元素事件的响应。在之前Button的例子中已经演示了它们的使用方式。请注意,传递给Handler的参数是个Sys.UI.DomEvent对象,它是一个跨浏览器的事件对象。在CTP的模型中,您使用全局的window.event对象进行操作,这并不是一个平台无关的对象。

Comment  虽然window.event不是个平台无关的对象,但是它依旧在多个浏览器运行良好,因为Atlas的Compact层为Event对象作了扩展,使它兼容了IE的操作。


Application Object and Life Cycle

在CTP版本中存在着RuntimeApplication两个对象的概念。其中Application对象负责分发window的事件,并且响应开发人员的pageLoad(通过load事件)和pageUnload(通过unload事件)的功能。pageLoad的功能保证了这些代码在所有的脚本和XML-Script已经被加载和初始化完毕后才被调用。

在RTM版本中将原来的Runtime对象和Application对象结合在了一起,成为了一个新的Application对象。在RTM版本中依旧保留了loadunload事件,另外还引入了新的init事件,一般用于使用$create来建立对象。您也可以像以前那样响应load事件来初始化对象。在RTM版本中,load事件在页面局部刷新的场景中也会被触发,因此如果您在pageLoad时操作对象的话,可能会由于round trip而重建对象。

使用$create语法在初始化对象时,保证了在实例化对象后调用了beginUpdate方法,然后设置属性,再依次调用了endUpdateinitialize方法。此外,对象被注册到了Application对象上,因此允许使用$find来找到这个对象的引用。


Property Change Notification

CTP版本和RTM版本都定义了property-change事件。在RTM版本中,如果您在开发组件,请在属性改变之后为其触发property-change事件,它提供了对于binding功能的支持,并能通知其他的事件监听器。

基础的Component类型已经实现了INotifyPropertyChange接口。


Disposing

在CTP版本中,基础类型Sys.Component已经实现了Sys.IDisposable接口,因而定义了dispose方法。这个模型在RTM版本中得到延续。不过在RTM版本中引入了一个新的接口:Sys.INotifyDisposing,它已经被Sys.Component实现了。这个接口允许Value-add包中的binding来监听一个对象的销毁,因此能够在合适的时候从组件上分离。

支持UpdatePanel功能的对象必须被销毁,因此您必须正确地实现它们的dispose方法以避免多次调用而产生的错误。例如在之前的Button示例中,dispose方法在调用$removeHandlerdelete之前进行了检查,以确定click handler的存在。

同时您也应该保证,在销毁任意的子组件或者对象前,要对它们进行检查,因为Application对象无法保证自动销毁对象时的顺序。


Bindings and Actions

在CTP版本中能够为一个组件定义Binding。因此只有存在一个组件,才能将Binding添加给它。

在RTM版本中并没有直接对Binding提供支持,但是提供了Sys.INotifyDisposing接口。有了这个接口,在Value-add包中的Binding就能在某个对象被销毁时得到通知,以此进行自我管理。因此,Value-add包中的Binding就能够脱离RTM包中组件运行,这也意味着与CTP版本相比,现在的Binding能够更加自由地进行声明和使用。

现在,Value-add包中的Binding能够获取一个source和一个target对象的引用,并且可以监听它们的销毁事件。当其中一个对象被销毁后,为两者建立联系的Binding也能独立地自行销毁。