Hello World
Spiga

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

2006-10-21 21:32 by 老赵, 3843 visits
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也能独立地自行销毁。

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

16 条回复

  1. neuhawk1[未注册用户]
    *.*.*.*
    链接

    neuhawk1[未注册用户] 2006-10-21 22:46:00

    支持,好勤快!

  2. 老夫子系
    *.*.*.*
    链接

    老夫子系 2006-10-21 23:15:00

    不错!

  3. Dah[匿名][未注册用户]
    *.*.*.*
    链接

    Dah[匿名][未注册用户] 2006-10-21 23:19:00

    有一个很关键的问题:
    应该是"ASP.NET AJAX", 而不是"ASP.NET 2.0 AJAX"
    ^_^
    再顶个~

  4. 老赵
    admin
    链接

    老赵 2006-10-21 23:38:00

    @Dah[匿名]
    您说的没错。
    以前的Atlas被分为了两部分,就像白皮书上的话:
    Summary: Describes changes to the Microsoft ASP.NET 2.0 AJAX Extensions and Microsoft AJAX Library (both products formerly codenamed "Atlas" and collectively referred to as ASP.NET AJAX) since the most recent Community Technical Preview (CTP) release.

    ASP.NET 2.0 AJAX Extentions和Microsoft AJAX Library分别对应于Server端和Client端两部分,我已经改过来了。:)

  5. Alan Cai[未注册用户]
    *.*.*.*
    链接

    Alan Cai[未注册用户] 2006-10-22 00:17:00

    现在的asp.net ajax存在一个大问题,就是不能像以前那样直接将dll文件拷到bin文件夹就可以使用,必须将该dll安装到Global Assembly Cache (GAC)。这可苦了使用虚拟主机的人了,服务器提供商肯定不可能安装beta或者rc版,估计就算正式版出来了,也不知道要拖到什么时候才支持,郁闷。

  6. 老赵
    admin
    链接

    老赵 2006-10-22 00:34:00

    @Alan Cai
    一点也没有错,我也是用虚拟主机的人。
    不过我想总会有办法的……

  7. Alan Cai[未注册用户]
    *.*.*.*
    链接

    Alan Cai[未注册用户] 2006-10-22 00:42:00

    @Jeffrey Zhao
    这个在weblogs.asp.net有人发表了关于这个问题的文章,不知道scottgu有没有回复,关注中……

  8. 老赵
    admin
    链接

    老赵 2006-10-22 01:00:00

    @Alan Cai
    我想是可以的。因为强命名的程序集能够放在GAC中,也能放在项目的Bin目录中使用。具体做法查一下MSDN应该就知道了。:)

  9. 小蜗牛
    *.*.*.*
    链接

    小蜗牛 2006-10-22 09:31:00

    哦@.@

  10. Hunts.C
    *.*.*.*
    链接

    Hunts.C 2006-10-22 11:45:00

    跟着Jeffrey 的步伐 哈哈@_@

  11. 老赵
    admin
    链接

    老赵 2006-10-22 12:15:00

    @Hunts.C
    我只是在入门,还没有开始真正的研究……:)

  12. 初步了解 ASP.NET AJAX 扩展[未注册用户…
    *.*.*.*
    链接

    初步了解 ASP.NET AJAX 扩展[未注册用户] 2006-10-23 16:14:00

    @Alan Cai: 关于 GAC
    我在配置文件中没有加入 GAC 引用,只是把 DLL 复制到 BIN,做了几个例子也成功了,不过太复杂的没有试。

  13. 老赵
    admin
    链接

    老赵 2006-10-23 16:56:00

    @初步了解 ASP.NET AJAX 扩展
    没错,我刚准备发文。:)

  14. adow[未注册用户]
    *.*.*.*
    链接

    adow[未注册用户] 2006-10-26 16:32:00

    象以前可以通过
    var draggablelistitem=new Sys.Preview.UI.DraggableListItem();
    draggablelistitem.set_handle(rss_title);
    rss_control.get_behaviors().add(draggablelistitem);
    来定义一个拖放行为,
    现在好象没有get_behaviors()了,按上面说的如果用$create该如何来写呢?

  15. jun[匿名][未注册用户]
    *.*.*.*
    链接

    jun[匿名][未注册用户] 2006-10-28 15:50:00

    一个DOM元素,可以关联(添加)一个Control和多个Behaviors,这是通过$create来建立关联的。可以通过DOM元素的control属性访问相关联的控件;通过DOM元素的behavior名字属性来访问一个behavior。

  16. adow[未注册用户]
    *.*.*.*
    链接

    adow[未注册用户] 2006-10-30 20:22:00

    @jun[匿名]
    $create(Sys.Preview.UI.DraggableListItem,{'name':'dli_'+ctrid},{},{},rss_div);
    var dli=$find(ctrid.toString()+"$dli_"+ctrid);
    dli.set_handle(rss_title);

    我这样写的,结果没有错误,用debug.dump看好象也没什么问题,但是也不能拖动。
    说实话,我对这样的写法不是很了解,感觉没有以前那样直观。

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我