AS3/Flex 4: la forma más práctica de encontrar niños anidados
actionscript-3 flex4 (3)
Estoy saltando de cabeza a algunas cosas de Flex / AIR. Tengo una base muy sólida con AS3, pero dada la complejidad jerárquica inherente de Flex (en comparación con Flash normal), me estoy encontrando con un problema.
Supongamos que tienes una aplicación donde casi todo es impulsado por eventos (común). El acceso a los elementos cercanos al objetivo del evento o al propio objetivo del evento es trivial. Estoy tratando de encontrar, sin embargo, la forma más práctica (leer: la mejor, la más eficiente) para encontrar niños que están muy alejados del contexto actual.
Sé que hay funciones como getChildAt()
y getChildByName()
, pero eso supone un contexto principal; ¿Qué pasa si el elemento (Flex) que está buscando es varios padres arriba, en un hermano, y luego varios niños abajo? Damos por hecho cosas como jQuery que hacen esto fácilmente, pero obviamente no tenemos ese lujo en AS3.
¿Alguno de los siguientes es válido? ¿Hay una mejor manera?
Itere a través de los padres y los padres de los padres hasta que encuentre un punto de parada, encuentre al hermano y repita a través de los niños y sus hijos hasta que encuentre su objetivo;
Mantenga los objetos clave en un almacén de objetos global (sic) y hágalos referencia cuando sea necesario (yech)
Use notación de puntos específicos para alcanzar el objetivo, incluidos los elementos (como máscaras y sus contenedores - yech nuevamente)
Cualquier pensamiento sería apreciado.
Editar:
Para aclarar, tomemos una aplicación Flex 4 AIR vacía. Obviamente, WindowedApplication
es la raíz, y agreguemos dos elementos SkinnableContainer
con los identificadores navContainer
y mainContainer
, respectivamente. Ambos tienen diseños personalizados. Dentro de mainContainer
, tenemos otro SkinnableContainer
con un diseño vertical e ID mainContent
, y como uno de sus hijos, tiene un objeto (cualquiera hará - un BorderContainer
chispa, tal vez) con la ID animatedBox
, por ejemplo. Dentro de navContainer
, tenemos un Button
chispa, que tiene un oyente vinculado a MouseEvent.CLICK
. Dentro de esa función, vamos a querer acceder a animatedBox
( nativeWindow.mainContainer.mainContent.animatedBox
) y animarlo para cambiar, digamos, su ancho.
El objetivo es acceder a ese distante DisplayObject
( animatedBox
) de una manera lo más discreta y eficiente posible, sin dejar de cumplir con los estándares Flex que claramente aún no he poseído. :)
Damos por hecho cosas como jQuery que hacen esto fácilmente, pero obviamente no tenemos ese lujo en AS3.
bueno, hay esto: http://tech.nitoyon.com/blog/2008/01/as3query_alpha.html
en mi implementación es fácil de hacer (sin embargo, está en AS3 puro):
en el objeto de visualización que maneja el clic:
private function onClick(e:MouseEvent):void{
Radio.broadcast(new CustomEvent(id, ..params));
}
en 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; }
}
}
y
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;
}
}
}
}
}
entregado como es;)
Me hice esta pregunta también muchas veces. Todavía no he encontrado una solución definitiva para el problema. Iterar a través de padres y padres definitivamente es una forma, pero debe tomarse con precaución, porque las relaciones pueden cambiar en su aplicación durante el tiempo de ejecución. Hace unos días, escribí un método simple que te permite iterar a través de todos los padres de un objeto determinado. Definitivamente no es una solución elegante pero funciona hasta ahora. El marco SWIZ también ofrece buenos métodos para facilitar la comunicación entre objetos a través de la inyección de código y la mediación de eventos. Tal vez vale la pena mirar ...