To pass a parameter to event listener in AS3 the simple way… does it exist?

前端 未结 5 1722
轻奢々
轻奢々 2020-11-28 04:00

Expected / pseudo example:

stage.addEventListener(MouseEvent.CLICK, onClick.someWayToPassParameters(true, 123, 4.56, "string"));
function onClick(e:         


        
相关标签:
5条回答
  • 2020-11-28 04:25

    I would modify Creynders example slightly:

        protected function createHandler(handler:Function, ...args):Function
        {
            var h:Function = function(e:Event = null):void
            {
                trace(args);
    
                if (handler != null)
                    handler(e);
            }
            return h;
        }
    
        sm.addEventListener(StyleEvent.STYLE_CHANGE, 
                createHandler(updateStyle, 1,true,"Lorem",["a","b","c"]), 
                false, 0, true);
    

    this way you can use original event handlers and inject the "arguments" to it,

    also you could have your handlers to have following signature:

    protected function myHandler(e:Event, ...args):void;
    

    then you could pass arguments directly to the target handler:

        protected function createHandler(handler:Function, ...args):Function
        {
            var h:Function = function(e:Event = null):void
            {
                //trace(args);
    
                if (handler != null)
                {
                    args.unshift(e);
                    handler.apply(this, args);
                }
            }
            return h;
        }
    

    best regards

    0 讨论(0)
  • 2020-11-28 04:32

    Passing a parameter directly to the event handler is not possible.

    The best approximation is by using a function factory method, IMO

    //--EDITED: I created a separate class to maintain parameterized handlers, see https://gist.github.com/4124722

    usage is simple:

        public class Usage extends Sprite{
    
            private var _handlers : ParameterizedHandlerContainer;
    
            public function ParameterizedEvents()
            {
    
                _handlers = new ParameterizedHandlerContainer();
                _handlers.registerHandler( this, Event.ADDED_TO_STAGE, someMethod, 3000 );
            }
    
            private function someMethod( event : Event, amount : uint ):void
            {
                trace( this, 'someMethod', amount );
                _handlers.destroyHandler( arguments.callee, event );
            }
    
    
        }
    

    Now you can register parameterized handlers with ParameterizedHandlerContainer#registerHandler and destroy them with ParameterizedHandlerContainer#destroyHandler.

    You can pass in any amount of parameters you want, but the first parameter of the callback method must be of type Event or a descendant.

    0 讨论(0)
  • 2020-11-28 04:36

    here is an example

    var s1:Boolean = true;
    
    station1.addEventListener(MouseEvent.ROLL_OVER, function(e:MouseEvent) : void { spread(e, s1) });
    station1.addEventListener(MouseEvent.ROLL_OUT, function(e:MouseEvent) : void { collapse(e, s1) });
    
    
    function spread(event:MouseEvent ,bb:Boolean):void {
     if(bb != true) event.currentTarget.gotoAndPlay(2);
    }
    
    function collapse(event:MouseEvent,bb:Boolean ):void {
        if(bb != true) event.currentTarget.gotoAndPlay(18);
    }
    
    0 讨论(0)
  • 2020-11-28 04:48

    Why not use AS3-Signals? Passing a parameter then is as simple as:

    import org.osflash.signals.Signal;
    
    public class AlarmClock 
    {
        public var alarm:Signal;
    
        public function AlarmClock() 
        {
            alarm = new Signal(String);
        }
    
        public function ring():void
        {
            alarm.dispatch("9 AM");
        }
    }
    
    0 讨论(0)
  • 2020-11-28 04:49

    Out of the box: it only takes 2 extra lines of elegant code to solve this ancient puzzle.

    stage.addEventListener(MouseEvent.CLICK, onClick(true, 123, 4.56, "string"));
    function onClick(b:Boolean, i:int, n:Number, s:String):Function {
      return function(e:MouseEvent):void {
        trace("Received " + b + ", " + i + ", " + n + " and " + s + ".");
      };
    }
    

    But most importantly, you will very likely need to remove the listener later to free resources, so +1 line to store it in a variable:

    var functionOnClick:Function = onClick(true, 123, 4.56, "string");
    stage.addEventListener(MouseEvent.CLICK, functionOnClick);
    function onClick(b:Boolean, i:int, n:Number, s:String):Function {
      return function(e:MouseEvent):void {
        trace("Received " + b + ", " + i + ", " + n + " and " + s + ".");
      };
    }
    

    And you'll be able to remove it normally:

    trace("Before: " + stage.hasEventListener(MouseEvent.CLICK));
    stage.removeEventListener(MouseEvent.CLICK, functionOnClick);
    trace("After: " + stage.hasEventListener(MouseEvent.CLICK));
    

    Here's a more elaborated, dynamic example to prove its use:

    function onClick(s:String):Function {
      return function(e:MouseEvent):void {
        trace("The square " + s + " at x = " + e.currentTarget.x + "px was clicked");
      };
    }
    var myFunctions:Array = new Array();
    for (var i:int = 0; i < 10; i++) {
      myFunctions.push(onClick("#" + (i+1)));
    }
    for (i = 0; i < myFunctions.length; i++) {
      var square:Sprite = new Sprite();
      square.name = "sqr" + i;
      square.addChild(new Bitmap(new BitmapData(20, 20, false, 0)));
      square.x = 5 + 25 * i;
      square.addEventListener(MouseEvent.CLICK, myFunctions[i]);
      stage.addChild(square);
    }
    

    No properties through dynamic objects, no custom class, no loose functions, no scope overlap. Just what logic expects it to be: you're simply passing arguments to it.

    And to remove every listener properly, you can do it like this later:

    for (i = 0; i < myFunctions.length; i++) {
      square = stage.getChildByName("sqr" + i) as Sprite;
      trace("Before (#" + (i+1) + "): " + square.hasEventListener(MouseEvent.CLICK));
      square.removeEventListener(MouseEvent.CLICK, myFunctions[i]);
      trace("After (#" + (i+1) + "): " + square.hasEventListener(MouseEvent.CLICK));
      stage.removeChild(square);
    }
    

    IMHO this is the simplest yet most solid way to do it.

    0 讨论(0)
提交回复
热议问题