Flex Data Binding详解

来源:互联网 发布:阿里云cdn流量包 编辑:程序博客网 时间:2024/05/16 07:56

 

Data BindIng简单的说就是当绑定源属性发生变化时,Flex 会把绑定源变化后属性的值赋给目的物的属性。做到了数据同步。

 

  Data BindIng 什么时候发生:

 

  1.在绑定源属性值发生改变时发生。

  2.在绑定源发出initialize事件时绑定发生一次。

 

  让属性具有可绑定功能:

 

   一般的,只要在属性前加上

  [Bindable]

  [Bindable(event="eventname")]

  元标记即可

  注意:

  如果没有标出触发绑定的事件,正如[Bindable]Flex会自动为绑定加上propertyChange事件,当源数据发生变化时,Flex将自动派发该事件,触发数据绑定。如果修改后数据和源数据“===”也就是全等,那么Flex将不会触发数据绑定。

  如果标出的触发绑定的事件,正如[Bindable(event="eventname")],那么在源数据发生改变的时候,必须dispatch出该事件才能触发数据绑定。不论修改后数据和源数据是否全等,Flex都将会触发数据绑定,需要自己编程控制,例如:

view plaincopy to clipboardprint?

<mx:Script> 

       <!--[CDATA[  

         [Bindable(event="hhhh")]  

         private var ss:String="aaa";  

           

         private function doTest():void  

         {  

          ss="bbb";  

f(ss!=="aaa") / /判断和源数据是否相等,不相等则触发绑定  

this.dispatchEvent(new Event("hhhh"));  

         }  

       ]]-->      

   </mx:Script> 

<mx:Text text="{ss}"/> 

<mx:Button click="doTest()"/> 

 <mx:Script>

        <!--[CDATA[

          [Bindable(event="hhhh")]

          private var ss:String="aaa";

         

          private function doTest():void

          {

           ss="bbb";

if(ss!=="aaa") / /判断和源数据是否相等,不相等则触发绑定

 this.dispatchEvent(new Event("hhhh"));

          }

        ]]-->   

    </mx:Script>

 <mx:Text text="{ss}"/>

 <mx:Button click="doTest()"/>

  如果没有this.dispatchEvent(new Event("hhhh"))这句,那么你点击按钮是没有设么作用的。 另外当申明自定义触发事件时,用ChangeWatcher来监控其变化,发现虽然目的源值变了,但是ChangeWatcher却监控不到变化,同样ChangeWatcher也监控不到非共有变量的变化。关于ChangeWatcher,下面会提到。

  绑定函数——Functions,对象——Object,数组——Arrays

  函数:

  你可以在{}中直接使用函数。例如:<mx:Text text="{Matn.random()*ss}"/>

  上面这个没有什么好讲的,关于函数绑定下面这个比较重要:

view plaincopy to clipboardprint?

 <mx:Script> 

       <!--[CDATA[  

         public var ss:String="aaa";  

           

         [Bindable(event="hhhh")]  

         private function gg():String  

         {  

          return ss;  

         }  

           

         private function doTest():void  

         {  

          ss=Math.random().toString();  

          this.dispatchEvent(new Event("hhhh"));  

         }  

       ]]-->      

   </mx:Script> 

     

<mx:Text text="{gg()}"/> 

<mx:Button click="doTest()"/> 

  <mx:Script>

        <!--[CDATA[

          public var ss:String="aaa";

         

          [Bindable(event="hhhh")]

          private function gg():String

          {

           return ss;

          }

         

          private function doTest():void

          {

           ss=Math.random().toString();

           this.dispatchEvent(new Event("hhhh"));

          }

        ]]-->   

    </mx:Script>

   

 <mx:Text text="{gg()}"/>

 <mx:Button click="doTest()"/>

  这样给函数加一个[bindable],便使函数具有绑定功能,但是如果不申明自定义触发事件,只能在组件初始化时绑定一次,点击以上按钮是没有什么作用的。大家可以自己试试。

 

  还有gettersetter函数,比较重要,给gettersetter函数加上[bindable],用不着两个都加,加一个就可以了,例如:

view plaincopy to clipboardprint?

<mx:Script> 

       <!--[CDATA[  

        public var ss:String="aaa";  

           

         [Bindable]  

         public function get gg():String  

         {  

          return ss;  

         }  

           

         public function set gg(value:String):void  

         {  

          ss=value;  

         }  

           

         private function doTest():void  

         {  

          gg=Math.random().toString();  

          this.dispatchEvent(new Event("hhhh"));  

         }  

       ]]-->      

   </mx:Script> 

     

<mx:Text text="{gg}"/> 

 <mx:Script>

        <!--[CDATA[

         public var ss:String="aaa";

         

          [Bindable]

          public function get gg():String

          {

           return ss;

          }

         

          public function set gg(value:String):void

          {

           ss=value;

          }

         

          private function doTest():void

          {

           gg=Math.random().toString();

           this.dispatchEvent(new Event("hhhh"));

          }

        ]]-->   

    </mx:Script>

   

 <mx:Text text="{gg}"/>

 <mx:Button click="doTest()"/>

  同样能达到绑定效果,如果只有一个getter方法,那么要想实现数据绑定,就需要申明自定义触发事件了,大家可以自己试试。

  对象:

  对象绑定最重要的是搞清楚怎么申明才能使其属性具有绑定功能,例如:

  申明对象 NonBindableObject

//[bindable]  先注释掉这行,测试

public class NonBindableObject extends Object

 {

   

        public function NonBindableObject() {

  super();  

        }

       

        public var stringProp:String = "String property";

 

        public var intProp:int = 52;

    }

绑定

 view plaincopy to clipboardprint?

<mx:Script> 

        <!--[CDATA[  

  [Bindable]  

  public var myObj:NonBindableObject = new NonBindableObject();  

  [Bindable]     

  public var anotherObj:NonBindableObject =   

      new NonBindableObject();  

  public function initObj():void {  

      anotherObj.stringProp = 'anotherObject';  

      anotherObj.intProp = 8;  

  }         

        ]]-->      

    </mx:Script> 

    <mx:Text id="text1" text="{myObj.stringProp}"/> 

    <mx:Text id="text2" text="{myObj.intProp}"/> 

    <mx:Button label="改变 myObj.stringProp"   

        click="myObj.stringProp = 'new string';"/> 

          

    <mx:Button label="改变 myObj.intProp"   

        click="myObj.intProp = 10;"/> 

          

    <mx:Button label="Change myObj"   

        click="myObj = anotherObj;"/> 

<mx:Script>

        <!--[CDATA[

  [Bindable]

  public var myObj:NonBindableObject = new NonBindableObject();

  [Bindable]  

  public var anotherObj:NonBindableObject =

      new NonBindableObject();

  public function initObj():void {

      anotherObj.stringProp = 'anotherObject';

      anotherObj.intProp = 8;

  }      

        ]]-->   

    </mx:Script>

    <mx:Text id="text1" text="{myObj.stringProp}"/>

    <mx:Text id="text2" text="{myObj.intProp}"/>

    <mx:Button label="改变 myObj.stringProp"

        click="myObj.stringProp = 'new string';"/>

       

    <mx:Button label="改变 myObj.intProp"

        click="myObj.intProp = 10;"/>

       

    <mx:Button label="Change myObj"

        click="myObj = anotherObj;"/>

 

  如果在申明对象时没有在类前加上[bindable]标签,那么该对象的所有属性是不能被绑定的,也就是说当对象属性发生变化时,不会触发绑定,所以点击前两个按钮都是没有用的,只有当该对象本身发生变化时,才能够触发绑定,正如第三个按钮的操作。

  现在取消第一行的注释,使对象属性可绑定,那么再点前两个按钮试试。只要给对象加上[Bindable]元标记,那么会使该对象的所有公有属性——public和拥有gettersetter方法的属性具有绑定功能。

  数组:

  如果把数组作为绑定对象,那么最好使用ArrayCollection对象,因为当使用ArrayCollection对象的一些API来操作数组会触发数据绑定,如:ArrayCollection.addItem(), ArrayCollection.addItemAt(), ArrayCollection.removeItem(), and ArrayCollection.removeItemAt()方法 ,不然要直接使用Array的话,只用当Array本身发生变化时才触发数据绑定,当数组中某一属性发生变化时是不会触发数据绑定的。例如:

 view plaincopy to clipboardprint?

<mx:Script> 

       <!--[CDATA[  

 import mx.collections.ArrayCollection;  

 [Bindable]  

 public var myAC:Array =["One", "Two", "Three", "Four"];  

       

 [Bindable]  

 public var myAC2:Array =["One1", "Two1", "Three1", "Four1"];  

       ]]-->      

   </mx:Script> 

   <mx:Text id="text1" text="{myAC[0]}"/> 

   <mx:Text id="text2" text="{myAC.getItemAt(0)}"/> 

   <mx:Button id="button1" 

       label="改变某一属性"   

       click="myAC[0]='new One'"/> 

   <mx:Button id="button2" 

       label="改变对象"   

       click="myAC=myAC2"/> 

 <mx:Script>

        <!--[CDATA[

  import mx.collections.ArrayCollection;

  [Bindable]

  public var myAC:Array =["One", "Two", "Three", "Four"];

     

  [Bindable]

  public var myAC2:Array =["One1", "Two1", "Three1", "Four1"];

        ]]-->   

    </mx:Script>

    <mx:Text id="text1" text="{myAC[0]}"/>

    <mx:Text id="text2" text="{myAC.getItemAt(0)}"/>

    <mx:Button id="button1"

        label="改变某一属性"

        click="myAC[0]='new One'"/>

    <mx:Button id="button2"

        label="改变对象"

        click="myAC=myAC2"/>

 

  当使用[]形式来申明数组时,必须使用ArrayCollectionAPI方法来实现数据绑定,所以当你点击第一个按钮时,text2发生了改变,而text1没有。

 数据绑定除了用[Bindable]标签来申明以外,也可以用<mx:Binding/>组件和ActionScript实现。

  <mx:Binding/>,例如:

  <mx:binding source="text1.text" destination="text2.text"/>

  <mx:binging source="text2.text" destination="text1.text"/>

  <mx:TextInput id="text1"/>

  <mx:TextInput id="text2"/>

  source为绑定源,destination为目的源,按上面的写法,不论是text1还是text2发生变化,都会引起对方的变化。细心的你也许会想这不会引起死循环吗?答案是否定的,不会引起死循环。我想应该是Flex内部的机制已经优化了这种情况,让其只触发一次。

  ActionScript来绑定:

  1.使用bindProperty()

   bindProperty(site:Object, prop:String,host:Object, chain:Object,commitOnly:Boolean = false):ChangeWatcher,例如:

   var myc:ChangeWatcher=BindingUtils.bindProperty(text2,"text",text1,"text");

   即当text1的值发生变化时text2也跟着变,site为目的对象,prop为目的属性,host为绑定源,chain为绑定源属性链——关于属性链下面再讲,commitOnly默认为False,即不管是确认事件还是未确认事件都将触发绑定,而为True时,只有确认事件才能触发绑定,这个一般用不到,和Flex自身的事件机制有关,如果为false的话,当数据改变时将触发两次绑定事件,当为True时,只触发一次,自己可以用bindSetter方法来做测试。当不想绑定时可以用myc.unwatch()方法来解除绑定。

  

  2.使用bindSetter()

  bindSetter(setter:Function, host:Object, chain:Object,commitOnly:Boolean = false):ChangeWatcher,例如:

  var myc:ChangeWatcher=BindingUtils.bindSetter(change,text1,"text",true);

  private function change(str:String):void

   {

   text2.text=str;

   }

  change就是当绑定源发生变化时所触发的函数,其他参数都一样。

  3.使用ChangeWatcher.watch()

  同样可以用ChangeWatcher.watch方法来监控对象属性的变化,非常有用。

  watch(host:Object, chain:Object,handler:Function,commitOnly:Boolean = false):ChangeWatcher,例如:

  var myc:ChangeWatcher=ChangeWatcher.watch(text1,"text",change)

  private function change(e:Event):void

   {

   text2.text=text1.text;

   }

  这里的Event和绑定数据所定义的触发事件有关,你可以用所有事件的父类Event来表示。

 

  注意:

 as主要是通过mx.binding.utils.BindingUtils 这个类来实现数据绑定,用MXMLas实现数据绑定有以下几点不同:

  1.当使用AS做数据绑定时,bindProperty() bindSetter()方法中不能使用AS代码,这和MXML是不同的, 可以用bindSetter() 方法来申明一个绑定处理函数。

  2.当使用AS做数据绑定时,同样不能使用EX4语法,也就是说不能直接使用XML解析语法了。

  3.当使用AS做数据绑定时,在属性链中不能使用任何函数和数组。

  4.MXML具有更好的错误提示和警告功能。

  最后来讲讲属性链。

  属性链就是bindProperty() bindSettet()等方法中的chain参数所表示的对象,  有时也许绑定源并不只是text1.text这样的简单形式,也可以是类似于user.name.text1.text,那么就存在一个关系链的问题,如果这条链中的某一项发生了改变,会不会触发绑定呢?答案是如果你想让其改变其中的某一项都能触发数据绑定,那么这条链的每个元素必须是可绑定的。对于上面的这种形式,可以这样使用bindProperty方法:

  bindProperty(text2, "text", this, ["user", "name","text1","text"])

 

 

 

 

原创粉丝点击