开发者

Simplify AS3 binding/event-dispatching code

开发者 https://www.devze.com 2022-12-13 08:16 出处:网络
There are 3 properties (example 1): [Bindable] public var name:String; [Bindable] public var email:Number;

There are 3 properties (example 1):

[Bindable] public var name:String;
[Bindable] public var email:Number;
[Bindable] public var address:Boolean;

I needed to have 3 helper methods that will be bindable too (example 2):

[Bindable] public var name:String;
[Bindable] public var email:Number;
[Bindable] public var address:Boolean;

public function get nameIsOk():Boolean     { return !Strings.isEmpty(name) }
public function get emailIsOk():Boolean    { return email == 3 }
public function get addressIsOk():Boolean  { return address }

Sure,开发者_如何学C the code above doesn't work. I made it work by doing this (example 3):

private var _name:String
[Bindable("nameChanged")]
public function get name():String       { return _name }
public function set name(v:String):void { _name = v; dispatchEvent(new Event("nameChanged")) }
[Bindable("nameChanged")]
public function get nameIsOk():Boolean  { return !Strings.isEmpty(name) }

private var _email:Number
[Bindable("emailChanged")]
public function get email():Number       { return _email }
public function set email(v:Number):void { _email = v; dispatchEvent(new Event("emailChanged")) }
[Bindable("emailChanged")]
public function get emailIsOk():Boolean  { return email == 3 }

private var _address:Boolean
[Bindable("addressChanged")]
public function get address():Boolean       { return _address }
public function set address(v:Boolean):void { _address = v; dispatchEvent(new Event("addressChanged")) }
[Bindable("addressChanged")]
public function get addressIsOk():Boolean  { return address }

It does work, but now it is bloated.

Is there a way to reduce this code (example 3) to something smaller (like example 2)?

UPDATE: Kudos to just_a_dude for nice answer. Here is the final version:

[Bindable] public var name:String;
[Bindable] public var email:Number;
[Bindable] public var address:Boolean;

public function Remixer() {
    for each (var f:String in Strings.split("name email address")) {
        ChangeWatcher.watch(this, f, onChange)
    }
}

private function onChange(e:PropertyChangeEvent):void {
    dispatchEvent(new Event(e.property + "Changed"))
}

[Bindable("nameChanged")]
public function get nameIsOk():Boolean  { return !Strings.isEmpty(name) }

[Bindable("emailChanged")]
public function get emailIsOk():Boolean  { return email == 3 }

[Bindable("addressChanged")]
public function get addressIsOk():Boolean  { return address }


Not sure if this is what you're looking for but you can use mx.binding.utils.ChangeWatcher to "watch" for property changes

<?xml version="1.0" encoding="utf-8"?>

<mx:Script>
    <![CDATA[
        import mx.events.PropertyChangeEvent;
        import mx.binding.utils.ChangeWatcher;


        [Bindable] public var firstName:String;
        [Bindable] public var email:Number;
        [Bindable] public var address:Boolean;

        private var _watcher:ChangeWatcher;

        private function init():void {
            ChangeWatcher.watch(this, "firstName", propertyChangeHandler);
            ChangeWatcher.watch(this, "email", propertyChangeHandler);
            ChangeWatcher.watch(this, "address", propertyChangeHandler);

            firstName = "foo";
            email = 0;
            address = true;

            firstName = "bar";
            email = 1;
            address = false;
        }

        protected function propertyChangeHandler(event:PropertyChangeEvent):void {

            var prop:Object = event.property;
            var name:String = prop.toString() + "Changed";

            // trace(name); // displays firstNameChanged or emailChanged or addressChanged

            dispatchEvent(new Event(name));
        }


    ]]>
</mx:Script>

Let me know if this helps

Cheers


I'm not sure if you need getters, but if not, a nice way to do it, is to just use a single function, and put your bindable strings as arguments.

if you put this in your object:

public function isOk(s:String):Boolean
{
    return !Strings.isEmpty(s)
}

You would use it like this:

<mx:CheckBox selected="{yourObject.isOk(yourObject.name)}" />

Generally, if you put a function inside the "{}" with parameters which are bindable, it will be called each time that parameter changes.


I would encapsulate your functionality in a class. Do not repeat yourself :)

0

精彩评论

暂无评论...
验证码 换一张
取 消