Bindable Flex中Bindable的原理

 [Bindable]        private var bind_String:String="hi";

    [Bindable(event="propertyChange")]
         private var bind_String:String="hi";
         
         private function onChange():void
         {
              var oldValue:String = bind_String;
              bind_String = "hello";
             if(bind_String!==oldValue) {
                 this.dispatchEvent(PropertyChangeEvent.createUpdateEvent(this,
                 "bind_String", oldValue, bind_String));
             }
         }

能用在哪里
三个地方:类, 变量, getter/setter。是不是public没有关系,private的就只能给自家用呗。用在Class上就是简单的给所有的public属性(包括变量,getter/setter,普通方法)加上[Bindable],可是一般的方法不能用[Bindable]呀,于是一般就能看到flex给了个warning,直接无视。变量嘛就是上面讲的,很简单略掉。

用在只读,只写属性(getter/setter)上面

终于讲到关键地方了,因为getter和setter很像方法,用起来会有点不同。看看这个例子:

[Bindable]
private var content:Array = new Array();
[Bindable]
public function set _content(ct:String):void
{
        content = ct.split(SEP);
}
[Bindable]               
public function get _wholeText():String
{
        if(content.length == 0)
        {
                return "";
        }
        else
        {
                var _w:String = "";
                for(var i:int=0 ; i<content.length ; i++)
                {
                        _w += content + "\r\n";
                }
                return _w;
        }
}

原来的设想是content绑定_wholeText,可它是不工作的。为什么?_wholeText太复杂了,被编译器排除在“可能”之外,编译器认为没有绑定关系,如果只是简单的return content,倒是可以的。我这里搜到了一些比较权威的解释。来自http://www.rubenswieringa.com/bl ... y-accessors-in-flex找到Ely Greenfield讲的。

    Now keep in mind that there’s no way for the compiler to actually tell if the value of a property get function would be different if called, short of doing an extensive code flow analysis of the get function, identifying all the inputs that might be affecting the value of the get function (i.e., member fields, statics, globals that are used in the get function and in any methods, global functions, closures, etc) it might call, and setting up watchers on every one of those to trigger the binding when any of them change. That’s prohibitively difficult, and expensive to do. So the compiler doesn’t try.

    Instead when you put [Bindable] on a get/set property, the compiler makes it bindable with a little creative rewriting that allows the framework to watch the get function, and dispatch a change event when the get function is triggered. This means that automatic bindable properties don’t work when the get function is computed from multiple values, or when you change its value by setting a backing field, rather than using the set function.

    It _also_ means that if you have no set function, we can pretty much guarantee that there’s no way automatically bindable get properties will be triggered. a read only propeerty is, to the compiler, completely opaque…at the moment, it has no idea where that value is coming from, and hence will never be able to ‘automatically’ trigger the binding.

说白了就是为了降低复杂度和提高效率,复杂情况的getter会被忽略。如何解决?可以手动建立绑定,即[Bindable("eventName")]。把代码改成这样:

[Bindable]
private var content:Array = new Array();
[Bindable]
public function set _content(ct:String):void
{
        content = ct.split(SEP);
        this.dispatchEvent(new Event("_contectChanged"));
}
[Bindable("_contectChanged")]               
public function get _wholeText():String
{
        if(content.length == 0)
        {
                return "";
        }
        else
        {
                var _w:String = "";
                for(var i:int=0 ; i<content.length ; i++)
                {
                        _w += content + "\r\n";
                }
                return _w;
        }
}

这样就避免了编译器去自动识别。自己加上绑定关系,当_content被赋值,发出_contentChanged事件,通知所有被绑定的getter方法执行一遍。这也说明了,绑定不过是事件游戏而已,flex为用户隐藏了很多底层算法。



绑定表达式或绑定的函数里抛出的异常和错误,被绑定框架所捕获,这种叫无声捕获。最终导致的结果就是,你通过Flash Player的debug版本去调试程序时,不能在运行时看到异常信息。不仅绑定功能没有工作,连错误都没显示出来。为什么会有这种无声捕获呢?在绑定情景出现前,代码需要满足绑定机制所必须的条件。绑定机制可以吞咽任何错误以阻止在运行时抛出异常信息。这样可以避免出现哪些不必要的错误提示信息。BindingManager.debugBinding("label.text")

实现了IPropertyChangeNotifier接口的类,当类的属性发生改变时,都会派发事件。举个例子,你可以查看UIComponent 类的代码。实际上UIComponent 类实现了,当属性一旦改变都会派发dispatchPropertyCangeEvent事件。

你可以通过给UserIfno类添加一个[Bindable]标签来解决绑定不工作的问题。这样就可以确保这个类的公有属性都可以被绑定。Flex编译器会生成相应的一对公有的getter和setter构造器,来确保它们满足绑定机制的要求。或者,若不希望所有属性可被绑定,可以将[Bindable]标签添加到类的指定属性上。

但是,有一些类的属性或变量,比如简单的变量,它们不能使用[Bindable]标签,也不能实现必要的接口。也就是说,这个类属于你创建的,你可以添加[Bindable]来轻松实现绑定的功能;但若这个类不属于你,而你又想实现绑定的功能,这时你就可以考虑使用ObjectProxy类。ObjectProxy 类包装一个非绑定类和一个属性改变就会派发的PropertyChangeEvent事件

在一个大量使用[Bindable]属性的类中,这个过程是很占用内存的。防治过度binding,忘记取消绑定或导致内存泄露


你要定义自己的常量以免造成过多的内存浪费。将一个静态常量赋值给事件的名称,并使用相同的值去派发事件。但是,当number值改变时,绑定没有工作。原因是事件的名称是EVENT_CHANGED_CONST,而不是这个常量的值。

一个普遍的错误是在绑定时,假定绑定的发生是按照一定的顺序来发生。这样可能导致你的程序发生警告提示和绑定不起作用。ActionScript中的事件是异步执行的方式。

双向绑定不起作用的原因在于源和目标对象的属性必须支持绑定,而且能够支持读和写的操作,只有这样才能支持双向绑定。

总之,数据绑定是Flex的很大的优点,但它也存在潜在的缺点。我建议在使用数据绑定时,你要花时间考虑该绑定是不是必须的,使用得是不是完全正确。滥用或误用会带来

内存的消耗,影响程序的性能。

http://blog.csdn.net/lixuekun820/article/details/5492697 经典


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Bindable.js 实现了灵活、快速的双向数据绑定的 JavaScript 库。 Two-way data binding means linking properties of two separate objects - when one changes, the other will automatically update with that change.  It enables much easier interactions between data models and UIs, among other uses outside of MVC. Bindable.js is similar to Ember's data-binding system, except it doesn't include anything View related, so the library has many use-cases - whether replacing Backbone's Model, providing a way to maintain the state between server <-> client for a realtime front-end application (similar to Firebase), or perhaps a way to communicate between server <-> server for a realtime distributed Node.js application. Projects using bindable.js Paperclip.js - data-bindable templating engine. Sherpa.js - online tours library Mojo.js - javascript MVC framework. AWSM - aws library. ditto - synchronized user interactions across browsers. 示例代码: var bindable = require("bindable"); var person = new bindable.Object({   name: "craig",   last: "condon",   location: {     city: "San Francisco"   } }); person.bind("location.zip", function(value) {   // 94102 }).now(); //triggers the binding person.set("location.zip", "94102");  //bind location.zip to another property in the model, and do it only once person.bind("location.zip", { to: "zip", max: 1 }).now(); //bind location.zip to another object, and make it bi-directional. person.bind("location.zip", { target: anotherModel, to: "location.zip", bothWays: true }).now(); //chain to multiple items, and limit it! person.bind("location.zip", { to: ["property", "anotherProperty"], max: 1 }).now(); //you can also transform data as it's being bound person.bind("name", {   to: "name2",   map: function (name) {     return name.toUpperCase();   } }).now(); 标签:Bindable

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值