Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3352064
  • 博文数量: 530
  • 博客积分: 13360
  • 博客等级: 上将
  • 技术积分: 5473
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-13 13:32
文章分类

全部博文(530)

文章存档

2017年(1)

2015年(2)

2013年(24)

2012年(20)

2011年(97)

2010年(240)

2009年(117)

2008年(12)

2007年(8)

2006年(9)

分类: Web开发

2011-11-04 16:45:18

1 概述
       [Bindable]是元标签,元标签不是语法的一部分,而是专门给编译器用的,是告诉编译器做某些事情。
       [Bindable]的作用是:告诉 flex编译器给某些某些东西建立绑定关系

       当你在没有添加事件设置的情形下使用 Bindable 标记时,propertyChange 是将被下发的默认事件类型。 因此,[Bindable] 标记等同于 Bindable(event="propertyChange")或[Bindable("propertyChange")]。

下面的代码
  1. [Bindable]
  2. public var testData:String;

 <mx:Text x="54" y="56" text="{testData}"/>

由于没有设置事件名称,编译器将创建下列代码:
  1. [Bindable(event="propertyChange")]
  2. public function get testData():String
  3. {
  4.    return this._1147269284testData;
  5. }

  6. public function set testData(value:String):void
  7. {
  8.    var oldValue:Object = this._1147269284testData;
  9.    if (oldValue !== value) {
  10.       this._1147269284testData = value;
  11.       if (this.hasEventListener("propertyChange"))
  12.          this.dispatchEvent(mx.events.PropertyChangeEvent.createUpdateEvent
  13.          (this, "testData", oldValue, value));
  14.       }
  15. }
     
Text控件监听propertyChange事件,如果有事件发生,则通过get方法修改其绑定的值

3 属性绑定

3.1 在类的属性之前
       格式为:
  1. [Bindable]
  2. public var foo;
    如果没有标出触发绑定的事件,正如[Bindable],Flex会自动为绑定加上propertyChange事件,当源数据发生变化时,Flex将自动派发该事件,触发数据绑定。如果修改后的数据和源数据“===”也就是全等,那么Flex将不会触发数据绑定。

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

点击(此处)折叠或打开

  1. <fx:Script>
  2.             <![CDATA[
  3.                 [Bindable(event="hhhh")]
  4.                 private var ss:String="aaa";
  5.                 
  6.                 private function doTest():void
  7.                 {
  8.                     ss="bbb";
  9.                     
  10.                     if(ss!=="aaa")//判断和源数据是否相等,不相等则触发绑定
  11.                         this.dispatchEvent(new Event("hhhh"));
  12.                 }
  13.             ]]>
  14.         </fx:Script>
  15.         
  16.         <mx:Text x="54" y="56" text="{ss}"/>
  17.         <s:Button x="94" y="56" click="doTest()"/>
     在变量ss上加Bindable,是说明该变量的值如果改变会派发hhhh事件,只要是跟该变量绑定的控件,就会监听这个事件。
     如果没有this.dispatchEvent(new Event("hhhh"))这句或[Bindable(event="hhhh")],那么你点击按钮是没有设么作用的。

      这么做还有一个好处,修改了默认的监听事件propertyChange,因为propertyChange事件会比较多,这样省略了大量的判定,提高了处理速度。
      如果我们想修改Bindable的事件,一般写代码时,会写成下面的格式。

3.2 在属性的getter或setter方法之前
      这是最常见的写法
      最好同时定义getter和setter方法,给getter或setter函数加上[bindable],用不着两个都加,加一个就可以了,例如

  1. <fx:Script>
  2.         <![CDATA[
  3.             
  4.             public var ss:String="aaa";
  5.             
  6.             var i:int=1;
  7.             var j:int=1;
  8.             
  9.             [Bindable("hhhh")]
  10.             public function get gg():String
  11.             {
  12.                 lb.text="get gg被调用"+i.toString();
  13.                 i++;
  14.                 return ss;
  15.             }
  16.             public function set gg(value:String):void
  17.             {
  18.                 ss=value;
  19.                 lb2.text="set gg被调用"+j.toString();
  20.                 j++;
  21.                 
  22.             }
  23.             private function doTest():void
  24.             {
  25.                 gg=Math.random().toString();
  26.                 this.dispatchEvent(new Event("hhhh"));
  27.             }
  28.         ]]>
  29.     </fx:Script>
  30.     <s:Label id="lb" x="180" y="30" text="get"/>
  31.     <s:Label id="lb2" x="180" y="60" text="set"/>
  32.     <s:Button label="{gg}" x="80" y="30" width="50" height="50" click="doTest()"/>
      注意Button中绑定的不能是ss变量,而是gg,如果是ss,点击按钮后,Button的label值不会修改。
网页刚启动时,结果如下

说明Button中label的值,是通过get gg()函数获取的。当我们点击一下按钮,结果如下

点击了一次按钮后,
      gg=Math.random().toString();使得set gg()函数被调用了次,
      由于派发了事件hhhh,监听器监听到后,调用get gg()修改了Button中label的值,而get gg()被调用了2次,多了一次,无法解释
 

4.对象绑定
     假设有一个对象NonBindableObject,拥有二个属性
      [Bindable]
      public class NonBindableObject extends Object{
          public var stringProp:String = "String property";
          public var intProp:int = 52;
      }

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

点击(此处)折叠或打开

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <s:Application xmlns:fx=""
  3.              xmlns:s="library://ns.adobe.com/flex/spark"
  4.              xmlns:mx="library://ns.adobe.com/flex/mx"
  5.              minWidth="955" minHeight="600"
  6.              creationComplete="initObj()"
  7.              >
  8.     <fx:Declarations>
  9.         <!-- 将非可视元素(例如服务、值对象)放在此处 -->
  10.     </fx:Declarations>
  11.     <s:layout>
  12.         <s:VerticalLayout/>
  13.     </s:layout>
  14.     
  15.     <fx:Script>
  16.         <![CDATA[
  17.             import mx.events.FlexEvent;
  18.             [Bindable]
  19.             public var myObj:NonBindableObject = new NonBindableObject();
  20.             
  21.             [Bindable]
  22.             public var anotherObj:NonBindableObject =new NonBindableObject();
  23.             
  24.             public function initObj():void {
  25.                 anotherObj.stringProp = 'anotherObject';
  26.                 anotherObj.intProp = 8;
  27.             }

  28.             
  29.         ]]>
  30.     </fx:Script>
  31.     
  32.     <mx:Text id="text1" text="{myObj.stringProp}"/>
  33.     <mx:Text id="text2" text="{myObj.intProp}"/>
  34.     
  35.     <mx:Button label="改变 myObj.stringProp"
  36.              click="myObj.stringProp = 'new string';"/>
  37.     
  38.     <mx:Button label="改变 myObj.intProp"
  39.              click="myObj.intProp = 10;"/>
  40.     
  41.     <mx:Button label="Change myObj"
  42.              click="myObj = anotherObj;"/>
  43.     
  44. </s:Application>


点击(此处)折叠或打开

  1. package
  2. {
  3.     [Bindable]//去掉后属性就会没有绑定效果
  4.     public class NonBindableObject extends Object
  5.     {
  6.         public function NonBindableObject()
  7.         {
  8.             super();
  9.         }
  10.         
  11.         public var stringProp:String = "String property";
  12.         
  13.         public var intProp:int = 52;
  14.     }
  15. }


      如果对对象进行绑定,则会绑定所有的public属性和拥有getter和setter方法的属性具有绑定功能。
    
5.数组与绑定
      如果把数组作为绑定对象,那么最好使用ArrayCollection对象,因为当使用ArrayCollection对象的一些API来操作数组会触发数据绑定,如:ArrayCollection.addItem(), ArrayCollection.addItemAt(), ArrayCollection.removeItem(), and ArrayCollection.removeItemAt()方法,不然要直接使用Array的话,只用当Array本身发生变化时才触发数据绑定,当数组中某一属性发生变化时是不会触发数据绑定的。

6.绑定的使用方式
6.1mx:Binding
      数据绑定除了用[Bindable]标签来申明以外,也可以用组件和ActionScript实现。
例如:
     
     
     
     

      source为绑定源,destination为目的源,按上面的写法,不论是text1还是text2发生变化,都会引起对方的变化。由于flex机制优化过,不会引起死循环。

6.2 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()方法来解除绑定。

6.3 使用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就是当绑定源发生变化时所触发的函数,其他参数都一样。

6.4 使用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 这个类来实现数据绑定,用MXML和as实现数据绑定有以下几点不同:
      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"])。

参考文献
1.Flex 2 中的元数据标签.
2.如何使变量进行Flex数据绑定. http://developer.51cto.com/art/201007/215153.htm
3.Flex Data Binding详解.
阅读(1911) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~