一 引用路径初探
在mxml中通过xmlns引用自定义组件时,默认的查找路径是首先在当前应用(application)的目录中寻找,如果没有找到,则会根据flex-config.xml中指定的ActionScript源代码目录下面去寻找:
<!-- List of path elements that form the roots of ActionScript class hierarchies. --> <!-- not set --> <!-- <source-path> <path-element>string</path-element> </source-path> -->
如果这两个地方都存在对应的文件,那么Flex会采用当前应用中的那个版本.
二 swc初探
swc是Flex组件的一种打包形式,它能够把swf文件和图片等资源文件打到同一个包中去,这样,就能够作为一个完整的功能组件进行发布了.
三 RPC初探
Flex中的RPC(Remote-procedure-call,远端程序调用)主要分为三类:
- 基于SOAP的WebService调用
- 基于URL的HttpService调用,一般返回XML数据
- 基于JAVA对象和AMF协议的RemoteObject调用
在mxml中,可以采用<fx:Declarations> 标签来声明RPC组件.
四 skin初探
skin能够通过修改或者覆盖组件的视觉元素的方式来改变组件的展示形式,skin能够定制组件不同状态(state)下的整体或者部分展示.
Spark和MX组件的一个巨大差异就在于,Spark组件完全依赖于skin来定制它的布局和展示,而MX组件使用CSS样式和skin协同控制它的展示,甚至,你可以完全不用skin而采用CSS来定制展示样式.
五 默认属性(default property)初探
组件的默认属性并不是指某个属性的默认值,而是指在不声明属性的情况下给组件赋值,这个值实际上是赋给了组件某个指定的属性,这个属性就被称为默认属性.
<?xml version="1.0"?> <!-- mxml\DefProp.mxml --> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark"> <s:layout> <s:HorizontalLayout/> </s:layout> <!-- Omit the default property. --> <s:List> <s:ArrayCollection> <fx:String>AK</fx:String> <fx:String>AL</fx:String> <fx:String>AR</fx:String> </s:ArrayCollection> </s:List> <!-- Explicitly speficy the default property. --> <s:List> <s:dataProvider> <s:ArrayCollection> <fx:String>AK</fx:String> <fx:String>AL</fx:String> <fx:String>AR</fx:String> </s:ArrayCollection> </s:dataProvider> </s:List> </s:Application>
在上面这段代码中,上下两个list的效果是一模一样的,而且都是合法的.在第一个list中,看似把某个ArrayCollection直接赋值给了list,其实是赋值给了list的默认属性dataProvider,所以才能达成和下面list一致的效果.
但需要注意的是,并不是所有的Flex组件都有默认属性的.
六 URL初探
MXML支持以下类型的URL:
- 绝对路径:
<fx:Style source="http://www.somesite.com/mystyles.css">
- 编译时使用的应用(application)相对路径
<fx:Script source="/myscript.as"/>
- 当前文件的相对路径
<fx:Script source="../myscript.as"/>
- 运行时的WEB工程路径
<mx:HTTPService url="@ContextRoot()/directory/myfile.xml"/>
注意, @ContextRoot()仅能够在WEB工程中应用,否则就需要设置context-root编译器参数.
七 ActionScript使用初探
在mxml中使用as脚本通常有两种做法,一是使用<fx:script source="*.as" />,二是使用<fx:script> include "*.as" </fx:script>.使用source时,可以使用绝对路径和相对路径,使用include时,只能使用相对路径.
八 对象自省(Object introspection)初探
针对Flex中的对象自省,通常有两种方法,一种是采用for..in循环,另一种是直接使用自省API.
需要注意的是,for..in循环仅能针对动态添加的属性进行自省,对于类定义中声明的属性以及方法是无法自省的,这就代表着,ActionScript API中的大部分类,在for..in循环中是不能自省出任何属性来的,下面我们看个for..in自省的例子:
<?xml version="1.0"?> <!-- usingas/IntrospectionForIn.mxml --> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark" creationComplete="initApp()"> <s:layout> <s:VerticalLayout/> </s:layout> <fx:Script> <![CDATA[ private var obj:Object = new Object(); private function initApp():void { // Create the object. obj.a = "Schotten Totten"; obj.b = "Taj Majal"; obj.c = "Durche die Wuste"; } public function dumpObj():void { for (var p:String in obj) { ta1.text += p + ":" + obj[p] + "\n"; } } ]]> </fx:Script> <s:TextArea id="ta1" width="400" height="200"/> <s:Button label="Dump Object" click="dumpObj()"/> </s:Application>
如果你需要内省非动态对象的相关属性,则需要采用flash.utils包中的describeType()方法,它唯一的参数就是你需要自省的对象,返回值是一个包含了属性描述的E4X XML对象.
需要注意的是,describeType()方法仅返回public的成员,看看样例:
<?xml version="1.0"?> <!-- usingas/IntrospectionAPI.mxml --> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark" creationComplete="getDetails()"> <s:layout> <s:VerticalLayout/> </s:layout> <fx:Script> <![CDATA[ import flash.utils.*; public function getDetails():void { // Get the Button control's E4X XML object description. var classInfo:XML = describeType(button1); // Dump the entire E4X XML object into ta2. ta2.text = classInfo.toString(); // List the class name. ta1.text = "Class " + classInfo.@name.toString() + "\n"; // List the object's variables, their values, and their types. for each (var v:XML in classInfo..variable) { ta1.text += "Variable " + v.@name + "=" + button1[v.@name] + " (" + v.@type + ")\n"; } // List accessors as properties. for each (var a:XML in classInfo..accessor) { // Do not get the property value if it is write only. if (a.@access == 'writeonly') { ta1.text += "Property " + a.@name + " (" + a.@type +")\n"; } else { ta1.text += "Property " + a.@name + "=" + button1[a.@name] + " (" + a.@type +")\n"; } } // List the object's methods. for each (var m:XML in classInfo..method) { ta1.text += "Method " + m.@name + "():" + m.@returnType + "\n"; } } ]]> </fx:Script> <s:Button label="This Button Does Nothing" id="button1"/> <s:TextArea id="ta1" width="400" height="200"/> <s:TextArea id="ta2" width="400" height="200"/> </s:Application>
ObjectUtil的getClassInfo()方法,也能够达到自省的目的.
九 事件初探
Flex针对事件的处理分为两侧,一侧是产生和抛出(dispatch)事件,另一侧是监听和消费事件,这两侧是多对多的关系.
事件的流转通常被划分为三个阶段:捕获阶段,命中阶段和冒泡阶段.
- 在捕获阶段,Flash Player会自顶向下地检查是否存在事件对应的监听,直到抛出事件的目标对象的父容器为止.如果这些父对象上面存在对应的监听,且监听器的use_capture参数设置为true时,就会调用对应的回调函数.
- 在命中阶段,Flash Player会检查抛出事件的目标对象自己是否存在对应的监听,如果发现对应的监听,则会调用对应的回调函数.
- 在冒泡阶段,,Flash Player首先会检查事件本身的bubbles属性是否为true,如果为true,则会从抛出事件的目标对象的父容器开始,自下向上地检查是否存在对应的监听,如果这些父对象上存在对应的监听,就会调用对应的回调函数.
Flex内建的事件主要位于三个包下面:spark.events.*,mx.events.*,flash.events.*.
addEventListener的语法如下:
componentInstance.addEventListener( event_type:String, event_listener:Function, use_capture:Boolean, priority:int, weakRef:Boolean )
需要注意的是,use_capture参数是指定对应的监听器在事件流转的哪个阶段起作用,如果设置为true,监听器会在事件的捕获阶段生效;如果设置为false,监听器则不会在捕获阶段生效,而在命中和冒泡阶段生效.它的默认值通常是false.
如果想要一个监听器能够在事件流转的所有阶段生效,就必须调用addEventListener两次,一次设置use_capture为true,另一次设置use_capture为false.
priority参数指优先级,优先级高的监听器会被首先执行,如果多个监听器的优先级相同或者都没设置优先级,则按照它们的添加顺序来执行.它的默认值是0,可以设置为正数或者负数.
当抛出事件的目标对象不在显示列表中时,事件是不会经过三个阶段的,比如派发给Socket类的事件,就只有命中阶段,而没有捕获或者冒泡阶段.
事件对象拥有两个属性:target和currentTarget.target是抛出事件的目标对象,而currentTarget是事件流当前的停留对象--即对此事件注册监听的对象.
stopPropagation()和stopImmediatePropagation()的区别在于,stopPropagation()不会阻止当前节点的其他监听器执行,而stopImmediatePropagation()会阻止当前节点的其他监听器执行.两者都阻止了事件流向下一个节点.