AS3 / Flex 4:寻找嵌套儿童的最实用方法

时间:2010-10-28 06:19:19

标签: flex actionscript-3 flex4 air

我有点直接跳到一些Flex / AIR的东西。我有一个非常扎实的AS3背景,但鉴于Flex固有的层次结构复杂性(与常规Flash相比),我遇到了一个问题。

让我们假设你有一个应用,其中几乎所有东西都是事件驱动的(常见的)。访问事件目标附近的元素或事件目标本身是微不足道的。然而,我试图找到最实用的(阅读:最佳,最有效)的方式来找到远离当前背景的孩子。

我知道有getChildAt()getChildByName()这样的函数,但它假定父上下文;如果您正在寻找的元素(Flex)是几个父母,在一个兄弟姐妹,然后几个孩子下来怎么办?我们理所当然地认为像jQuery这样容易做到这一点,但显然我们在AS3中没有那么奢侈。

以下任何一种情况有效吗?还有更好的方法吗?

  1. 通过父母和父母的父母进行迭代,直到找到一个停止点,找到兄弟姐妹,并在孩子和他们的孩子之间进行迭代,直到找到目标为止;

  2. 将关键对象保存在全局对象库(原文如此)中并根据需要引用它们(yech)

  3. 使用特定的点符号到达目标,包括元素(如皮肤及其容器 - 再次表示)

  4. 任何想法都会受到赞赏。

    修改

    为了澄清,让我们来看一个空的Flex 4 AIR应用程序。显然,我们以WindowedApplication作为根,让我们分别添加两个ID SkinnableContainernavContainer的{​​{1}}个孩子。两者都有自定义皮肤。在mainContainer中,我们有另一个mainContainer,其中包含垂直布局和ID SkinnableContainer,并且作为其子项之一,它有一个对象(任何会做 - 一个火花mainContent例如,或许)ID为BorderContainer。在animatedBox中,我们有一个spark navContainer,它有一个绑定Button的侦听器。在该函数中,我们将要访问MouseEvent.CLICKanimatedBox)并对其进行动画处理以更改,例如,它的宽度。

    目标是以尽可能不引人注目和高效的方式访问那个遥远的nativeWindow.mainContainer.mainContent.animatedBoxDisplayObject),同时仍然符合我明显尚未拥有的Flex标准。 :)

3 个答案:

答案 0 :(得分:1)

在我的实现中很容易做到(但它在纯AS3中):

处理点击的显示对象:

private function onClick(e:MouseEvent):void{
    Radio.broadcast(new CustomEvent(id, ..params));
}

在animatedBox中:

Radio.addListener(id, new Reciever(uid, animate));

private function animate(e:CustomEvent) {
   //needed code and access of CustomEvent props you pass
}

UPD:

package lazylib.broadcast 
{
    /**
     * ...
     * @author www0z0k
     */
    public class Reciever 
    {
        private var id: String;
        private var toRun: Function;
        /*@param nm - unique listener id - required
         *@param fn - event handler function - required*/
        public function Reciever(nm:String, fn:Function) 
        {
            id = nm;
            toRun = fn;         
        }

        public function onEvent(e:* = null):String {
            if (e == null) { return id; }
            toRun(e);
            return id;
        }

        public function get ID():String { return id; }

    }

}

package lazylib.broadcast
{
    import flash.events.Event;
    import flash.events.EventDispatcher;
    /**
     * ...
     * @author www0z0k
     */
    public final class Radio extends EventDispatcher
    {
        private static var listeners: Object = new Object();
        private static var archive: Array = new Array();
        private static var forSlowpokes: Object = new Object();

        public static function get ForSlowpokes():Object { return forSlowpokes; }

        public static function addListener(type: String , listener: Reciever):Boolean {
            listeners['anchor'] = null;
            if (!listeners[type]) { 
                var o: Object = new Object();
                listeners[type] = o;
            }
            if (!listeners[type][listener.ID]) {
                listeners[type][listener.ID] = listener; 
                return true;
            }else {
                return false;
            }
        }

        public static function broadcast(evt: * , singleUse:Boolean = false):void {
            var type:String = (evt as Event).type;          
            if (listeners[type]) {
                var returned: Array = new Array();
                for (var i: String in listeners[type]) {
                    if(listeners[type][i]){
                        var fnRetVal: String = listeners[type][i].onEvent(evt);
                        returned.push(fnRetVal);
                    }else{
                        //trace("no listener for id = " + i + ' , type = ' + type);
                    }
                }

            }else {
                //trace("nobody's interested in : \"" + type + "\"");
            }
            if (singleUse) {
                forSlowpokes[type] = 'you missed it realtime';
                delete listeners[type];
            }
        }

        public static function clearDeadFuncs(namez:Object):void {
            for (var a:String in namez) {
                if (a != 'anchor') {
                    killListener(a, namez[a]);
                }
            }
        }

        public static function killListener(type: String , id: String):Boolean {
            if (!listeners[type]) { 
                //trace("there are no listeners for event : " + "\"" + type + "\"");
                return false;
            }else {
                if (!listeners[type][id]) {
                    //trace("there is no \"" + id + "\" listener for event : " + "\"" + type + "\"");
                    return false;
                }else {
                    listeners[type][id] = null;
                    //trace("removed listener \"" + id + "\" for event : " + "\"" + type + "\"");
                    var evt2kill: Number = 0;
                    for (var str: String in listeners[type]) {
                        if (listeners[type][str]) {
                            evt2kill++;
                        }
                    }
                    if (evt2kill == 0) {
                        delete listeners[type];
                        //trace("no more listeners for event : " + "\"" + type + "\"");
                        return true;
                    }
                    return true;
                }
            }
        }
    }
}

按原样交付;)

答案 1 :(得分:0)

  

我们理所当然地认为像jQuery这样容易做到这一点,但显然我们在AS3中没有那么奢侈。

这就是:http://tech.nitoyon.com/blog/2008/01/as3query_alpha.html

答案 2 :(得分:0)

我也问了很多次这个问题。还没有找到问题的最终解决方案。通过父母和父母进行迭代绝对是一种方式,但必须谨慎对待,因为在运行时期间应用程序中的关系可能会发生变化。几天前我写了simple method,让你迭代一个给定对象的所有父级。绝对不是一个优雅的解决方案,但它到目前为止工作。 SWIZ framework还提供了很好的方法来通过代码注入和事件中介来促进对象之间的通信。也许值得一看......