chapter 2 getting started
?
1、自定义组件命名空间格式:xmlns:Tag="包名"。例如:xmlns:MyComps:com.humanmonth.*。调用格式:<tag:ClassName />。例如:<MyComps:MyImage/>。
?
2、swc是flex组件的归档文件。
?
3、数据绑定。一、在mxml中,组件用{}引用其它数据。当被引用数据被更改时,组件的{}值也会这被更新。
?
4、flex的远程方法调用(Remote-procedure-call[rpc])用于flex与服务端交换数据(发送/接收)。flex有多种RPC服务,包括soap,amf(java),http。MXML包含以下几种类型的RPC组件:soap、httpservice、remoteobject(amf protocol)。
?
5、在mxml文件中,在<fx:Declarations>标签内定义一些非可视化组件。
?
6、数据模型(data model)。数据模型用于存储数据。可以使用标签<fx:Model>,<fx:XML>,<fx:XMLList>或as类。
?
7、用<fx:Model>定义数据模型的方法类似于直接写xml。例如:<fx:Model?id="myId"><myName>tt</myName></fx:Model。
?
8、数据验证。可以在mxml的<fx:Declares>标签中声明验证器,格式:<mx:EmailValidator source="{被验证元素的ID}" property="text"/>
?
9、使用样式表(css)。如果在mxml中使用<fx:style>标签,即<fx:style>标签必需要mxml文档根元素的直接子元素。
?
10、常用的css选择器有class选择器和type选择器。使用type选择器时需要使用命名空间,语法如下:@namespace s "library://ns.adobe.com/flex/spark"; s|Button{}。
?
11、mx及spark架构中的一个主要区别是Spark组件依赖皮肤去定义布局及外观。而mx组件依赖样式及皮肤。用mx组件时,你更多地去用样式而用Spark时,你更多地是用皮肤是处理布局及外观。
?
12、使用效果(effect)。使用效果的步骤是先在<fx:Declarations>中定义一个效果,并在target中指明效果应用到的组件。然后在组件的相关事件中调用效果:effectId.play()。
?
13、用mxml自定义组件。步骤:找一个和自定义组件相近的类,然后在里面添加或修改一些方法。调用方法与actionscript的自定义组件方法一样。
?
14、在mxml中引用as中的静态变量时,使用{fullpackage.class.Name}型式。
?
15、设置默认属性(setting the default property)。很多flex组件定义一个单独的默认属性。默认属性是一种速记机制,让用户不用输入属性名的情况下设置值。例如<s:List><s:ArrayCollection>与<s:List><s:dataProvider><s:ArrayCollection>是相等的。而里面的dataPrivider是默认属性。另外要注意,并不是所有的组件都有默认属性。
?
16、在mxml中使用转义字符。若在mxml中使用字符中有数据绑定或转义符。即用正斜线转义。例如:\{,\\。
?
17、换行符。你可以使用‘\n’或‘ ’来代表换行。
?
18、在定义一些变量前加上[Bindable]标记表示当该变量改变时,引用该变量的对像会被通知/自定修改。
?
19、引入样式或脚本的语法:<fx:Style source="url",<fx:Script source="url"。
?
20、在mxml中设置正则表达式属性:/regex/flags。
?
21、用法上,as与mxml的关系与js和html相似。而编译的角度看,as与mxml的关系和servlet与jsp相似。
?
22、无论是<fx:Script>还是<fx:Style>都必需是mxml文件根节点的子节点。
?
22、使用<fx:Script>,请在里面加上<![CDATA[]]>。
?
23、MXML中,每个元素都有一个ID属性。你可以直接通过ID引用该元素。如果元素没有设置ID,你可以通过元素的父元素的getElementAt()、getChildAt()方法获取元素。最后,你还可以通过方括号[名称]的方式来获取元素。
?
24、this是对当前文档、对像、闭包的引用。
?
25、在as中创建可视元素的步骤是:先创建元素,然后加入到容器,最后设置元素的属性。创建元素后,如果不加入到容器中,对像不会被显视。加入容器的语法是MX架构:addChild()/addChildAt(),Spark架构:addElement()/addElementAt()。
?
26、默认情况下,元素被加入到容器的最后一个元素后面。如果你要指定顺序,即需要用addElementAt()或调用addElement()后调用setItemIndex()。前者效率会高一点。
?
27、删除元素。在Spark中,可以用removeELement(),removeElementAt(),removeAllElements()方法删除元素。如果要是MX架构,即用Child替换上面的Element。
?
28、当调用容器的remove相关函数后,元素就会从显视列表中去除。然而这并不代表对像会被GC删除。紧当被删除元素在外面没有被引用时。flashGC才会在适当的时候删除对像。适时删除无用元素会大大改善性能。
?
29、只有实现了IVisualElement接口的对像才能加入到显视列表的容器中。如果对像没有实现IVisualElement接口而想加入到显视列表时,可以把对像先放到UIComponent后再加入到显视列表。例如:new UIComponent().addChild(new Sprite());
?
30、引用。FlexGlobals.topLevelApplication是对根application的引用。parentDocument是在文档链中对当前文档的上一层文档的引用。parentApplication是在应用链中对当前应用的上一层应用的引用。当被载入的应用与主应用不在同一应用域(ApplicationDomain)或安全域(SecurityDomain)时,上述引用不会生效。
?
31、在mxml中,元素的事件属性代码在mxml编译后会变成一个方法。所以在元素事件属性中的代码的this是对文档的引用而不是那个元素。
?
32、在mxml中引用as代码有两种方法,一种是<fx:Script source="pac/pac/fileName.as" />。另一种是include指令:include "filename";格式:<fx:Script>include "pac/filename.as"</fx:Script>。source支持相对或绝对路径。而include指令紧支持相对路径。include指令可放在if语句中(语句块中要求只有include指令)。
?
33、as的内省(introspection)机制有两种。它们常在调试过程中使用。一种为for in 循环。另一种为as的api。
?
34、for in循环会把动态加入的属性及方法打印出来。然后大部份的as对像并不是动态对像,所以的for?in循环中,绝大部份对像不会显视属性及方法。用for in循环打印动态属性及方法与用mx.utils.ObjectUtil.toString()方法的效果一样。
?
35、内省api。flash.utils.desctibeType() 。它们打印出public属性及方法而不会打印私有的。返回的结果为一个xml。
?
36、事件可以让程序员知道事情发生。鼠标、键盘、网络请求、组件生命周期等等都会触发事件。
?
37、flash显视列表的根元素为Stage,往下为:SystemManager->Application->其它显视组件。这个列表我们称为显视列表(display list)。
?
38、显视列表的事件模型:捕获-》目标-》冒泡。即发生事件后,事件会延着显视列表树从顶层到目标然后再冒到顶层。
?
39、事件被触发时,fp(flash player)会创建一个事件对像,然后这个事件对像将在事件的三个阶段中传递。在传递过程中,事件对像的某些属性会被改变。你可能通过这些属性知道事件的所在的阶段。
?
40、flash.events.Event为事件的基类。他的子类分布在spark.events.*,mx.events.*,flash.events.*中。另外还有一些特殊作用的事件类分布在另外一些包中。例如mx.messaging.events
?
41、显视列表中的任何对像都继承自DisplayObject,而DisplayObject继承自EventDispatcher。EventDispatcher为显视列表中的所有类提供了事件模型的功能。
?
42、显视列表中的任何对像都可以通过继承自EventDispatcher的addEventListener来监听事件。只要事件流通过该对像,该对像的监听器都会被触发。
?
43、EventDispatcher从名称上说,主要功能为分发事件。但在使用过程中,更多是用于添加与移动监听事件。
?
44、当你需要事件模型中的功能,但又不能继承EventDispatcher时,可以实现IEventDispatcher接口。
?
45、除了由fp发送事件对像外,有些时候你可能需要自已发送事件。这时你可能通过dispatchEvent方法发送自定义事件到事件流中。
?
46、event对像中的target为触发事件的对像。currentTarget为正在处理事件的对像。
?
47、在mxml的元素中的事件属性直接添加事件时,如果使用click=functionname()时,event对像不会被传入到方法中。如果要传入event对像,需要click=functionname(event);
?
48、addEventListener中的use_capture参数为true时表示监听器在捕获阶段被调用,如果为false表示在冒泡阶段被调用。如果不指定,那默认值会根据事件类型的不同而不同。如果你需要在事件的两阶段都解发事件,那你需要调用两次addEventListener。use_capture参数一次为true,另一次为false。
?
49、addEventListener中的priority。如果不设置,priority默认值为0。这种情况下,先调用addEventListener的监听器会先被调用。如果设置了priority,即priority的值越高,越早被调用。
?
50、addEventListerer中的weakRef。默认为false。如果此值为false,即此监听器不会被GC回收。如果为true,此监听器会被GC回收。
?
51、方法闭包在每次被调用时都会被创建。闭包的作用域在定义它的地方而不在调用它的地方。例如,闭包内引用外面的一个变量y,在调用它的方法外面也有一个变量y。即运行时,闭包引用的是定义的类中的y。
?
52、在addEventListener中使用闭包时,参数中的userWeepRef如果设为true,在gc运行时可能会把闭包回收。这样会出现不可预期的错误。
?
53、类级别的定义不会被GC回收,闭包除外。
?
54、使用addEventListener设置的监听器不再被使用时,应该用removeEventListener移除。而在mxml中直接给onclick付值的方式增加的监听器不能被移除。
?
55、为一个对像的同一种类形事件添加多个触发器的方法:在mxml的事件属情中有分号隔开多个监听器。例如:listener1();listener2()。或者利用addEventListener多次:obj1.addEventListener(click,m1);obj1.addEventListener(click,m2);
?
56、在监听器中实现多个参数。由于addEventListener参数中的function是一个方法,且参数固定为event。如果要实现监听器多参数,方法有三个。一、闭包。因为闭包中变量的作用域是定义它的地方。例如:obj.addEventListener("click",function(event){fun(p1,p2)}。二、在mxml的标签属情中设置监听器,因为在mxml中设置监听器时,参数是随意的。例如click="fun(event,p1,p2)"。三、把参数放在currentTarget对应的对像中。在实际使用过程中,第三种方法最简单。
?
57、手动分发事件。由于UIComponent->DisplayObject->EventDispatcher。所以显视列表中的所有对像都有dispatchEvent()方法。例如:obj.dispatchEvent(new Event("click"));
?
58、显视列表中的大部份对像的事件都经历事件模型中的三个阶段(捕获、目标、冒泡)。而不在显视列表中的对像也具有相同的事件模型,但只有(目标)阶段,例如socket的响应。另外, 在显视列表中的格式对像、验证对像也同样只有目标阶段。
?
59、默认情况下,所有的监听器都只注册在目标及冒泡阶段,除非你手动注册一些在捕获阶段的监听器-addEventListener("click",func,true);
?
60、当你在一个对像中监听一个click事件。当该监听器响应时,并不一定代表是该对像dispatch的。很多情况下是该对像下的子对像触发的。所以要区分好event中的target及currentTarget。
?
61、stopProgragation()与stopImmediatePropagation()的作用都是停止事件的传递,前者是阻止节点后面的事件被调用。后者是阻止当前节点当前事件往后的事件被调用。
?
62、无论是stopProgragation()还是stopImmediatePropagation()都阻不了默认事件的执行。例如Event.Close等。
?
63、在一群组件中调用addEventListener注册同一个方法的效率比较低(性能与内存)。可以考虑把方法注册在父组件中。例如在流程图中有一大群节点。如果在所有节点中都注册一些移动事件,这样效率很低下。可以考虑把事件注册在容器中,然后从target中获取标识。再使用container[pre_id]获取组件。这种做法可以加快应用的启动速度及减小内存占用。
?
64、一般把监听键盘的任务放在最外层容器中。这样可以统一管理。例如:FlexGlobals.topLevelApplication.addEventListener(KeyboardEvent.KEY_UP,fun)。另外需要注意,在app初始化后,FlexGlobals.topLevelApplication并不接收事件,你需要让其中的任一个组件聚焦后,它才会接收到事件。
?
65、keyCode与charCode的区别在于keyCode代表键盘上的一个键,而charCode代表该键产生的utf8的一个值。例如k与K的keyCode是相同的,而charCode不同。
?
66、判断组合键的方法。例如判断是否为shift+q:if(event.shiftKey){if(event.keyCode==81){}}。
?
67、关于操作系统、浏览器与fp接收事件的顺序。os第一,浏览器第二,最后才是fp。所以当浏览器拦截了事件并关阻止事件后,fp会收不到事件。
?