2006年11月3日星期五

Microsoft Ajax Beta1 - 边学边用边补充 (Part 4 - $create)

在Beta1之前,我们可以使用Xml-Script定义对象,当然也可以用JavaScript的老方式来定义对象,不过用过后者的人肯定会觉得这种方式不太方便,因为大多数Control和Behavior都需要手动调用initialize后才能正常运作。例如CTP中的Button,不执行initialize就不会绑定DomElement的click事件,它自身的click事件也就不能被正常触发。还有beginUpdate和endUpdate的初次运行也由Xml-Script的解释器负责,在JavaScript中你就需要自己负责了。

在Beta1里面,终于有一样东西可以让你方便地定义对象,同时不需要自己负责这些琐碎的必要执行项目,那就是$create指令,它的参数列表是$create(type, properties, events, references, element)。从名称上看这几个变量都很好解释,但实际上不是那么简单,现在逐个来说:

type

你要创建的对象类型,必须是继承自Sys.Component的,例如Sys.UI.Control或者Sys.UI.Behavior。注意这里说的是继承自,也就是你不能用$create创建一个Sys.Component,这应该是一个bug。

properties

你要为新建对象所提供的初始属性。对于属性名称,设置时会先确定其get方法和set方法是否存在,如果都存在就直接用set方法赋值。如果不是呢?这就要分支判断了,我不想用文字解释代码,所以我用例子解释可能有哪些分支:

  • get方法不存在,要设置的是公开的成员变量,那么{Property:"Value"}的赋值行为就是instance["Property"]="Value"。
  • get方法不存在,则可能是公开子对象深层次赋值。例如处理{Sub:{Property:"Value"}}的赋值行为就是instance.Sub.set_Property("Value")。如果是更多层的公开子对象,程序也能为你递归处理。
  • get方法存在而set方法不存在,传入的是Array,则通过get方法获取原本的Array,然后进行Array覆盖。
  • get方法存在而set方法不存在,则也可能是深层次赋值。同样是{Sub:{Property:"Value"}},这种情况赋值行为就是instance.get_Sub().set_Property("Value")。更深层次的递归调用赋值也是当然的。

这些例子的思路很不严谨,仅仅是为了让大家明白到没有get方法或没有set方法时可能会是什么情况。要严谨的就自己去看Sys$Component$_setProperties函数,参照着上述分析很容易看明白。

events

你要为新建对象提供的初始化事件。这个解释起来就简单多了,$create中仅仅检查事件名称对应的add方法是否存在,存在就添加,不存在或者要添加的不是function就抛出异常。

references

这个参数暂时没有任何资料有提到过,但是从代码看得出是用于设置对其他Component的引用,这些引用实质上也是一种属性。和properties不同,reference传入的属性值不是真正要赋值的实例,而是Component的名称,然后通过$find找到这个Component的实例并用set方法赋值。$find找不到实例或者set方法不存在都会导致抛出异常。如果大家还记得Xml-Script的写法,那就会想到Component之间交叉引用是很正常的,如果你在Application的initialize阶段进行$create,那么$create将享受和Xml-Script等同的待遇,也就是允许交叉引用。你可以按你喜欢的顺序用$create声明Component,即使先声明的在reference中提到后声明的名称没问题,因为Application的initialize阶段结束时这些reference才真正赋值。但是过了这个阶段就没有这种待遇了,reference中提到的名称必须都是已存在的Component,否则将引发异常。

element

你要新建的对象关联的DomElement。如果你创建的是Sys.UI.Control或Sys.UI.Behavior的子类,则必须由element,否则必须没有element。和type一样存在的bug就是,如果你想创建一个Sys.UI.Control,那么你自己会要关联一个DomElement,然后一个异常被抛出来提醒你不应该有element。

说完了这5个属性,是不是发觉这看起来简单的$create其实一点都不简单呢,这就是为了保证$create能够获得和Xml-Script一致的效果。它们的效果真的一致吗?书写起来不是Xml-Script更美观吗?Jeffrey向来支持Xml-Script,有了$create之后我选择支持$create,因为你将发现它的书写方式并不比Xml-Script要丑陋。

大家可以先看看Dflying使用ASP.NET Atlas实现拖放(Drag & Drop)效果(下),那个声明DragDropList和DraggableItem的Xml-Script看起来不错吧。然后来看看我的使用$create的DragDropList与DraggableItem声明,是不是层次感也不比Xml-Script差?Xml-Script的层次感来自于XML,而$create的层次感来自于JSON,因为那些properties、events、references都是使用JSON表达式书写的。

没有评论:

发表评论