要将参数传递给AS3中的事件侦听器,这种方法很简单......它是否存在?

23 flash parameters events actionscript-3 addeventlistener

预期/伪示例:

stage.addEventListener(MouseEvent.CLICK, onClick.someWayToPassParameters(true, 123, 4.56, "string"));
function onClick(e:MouseEvent):void {
    trace("Received " + someWayToRetrieveParameters().b/i/n/s + ".");
}
Run Code Online (Sandbox Code Playgroud)

多年(3~4),在每个网站,论坛,博客,无论我在哪里搜索,人们告诉我没有简单的方法来做到这一点.他们通常建议:

  • 将侦听器添加到动态对象,您可以在其中将值设置为额外属性并在函数中引用它(e.target.property/e.currentTarget.property).

    并非所有课程都是动态的.例如,它不适用于Sprite.

  • 使用自定义类扩展对象的类以添加属性或仅使其动态化.

    你每次都要创建一个全新的tweak课程.

  • 使用匿名函数作为事件处理程序.

    没有参考(而且很难看).要删除侦听器以释放资源,您必须使用arguments.callee从函数内部执行此操作.

  • 在事件处理程序中使用参数调用另一个函数.

    在事件处理程序调用的位置参数是什么?

  • 将事件处理程序保持在与参数相同的范围内.

    违反完全语义混乱.

  • 在接收目标和参数的函数中封装事件处理程序定义和addEventListener调用.

    它可以混合范围,但它是一个接近的范围.但是你必须要小心.

......在许多其他建议的解决方法中.

我想要的只是将一个参数传递给事件处理程序,这样我就可以在其函数中使用它,就像任何普通的函数一样!

我要求太多了吗?

小智 87

开箱即用:它只需要2行额外的优雅代码来解决这个古老的难题.

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 + ".");
  };
}
Run Code Online (Sandbox Code Playgroud)

但最重要的是,您很可能需要稍后删除侦听器以释放资源,因此+1行将其存储在变量中:

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 + ".");
  };
}
Run Code Online (Sandbox Code Playgroud)

你将能够正常删除它:

trace("Before: " + stage.hasEventListener(MouseEvent.CLICK));
stage.removeEventListener(MouseEvent.CLICK, functionOnClick);
trace("After: " + stage.hasEventListener(MouseEvent.CLICK));
Run Code Online (Sandbox Code Playgroud)

这是一个更详细,动态的例子来证明它的用途:

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);
}
Run Code Online (Sandbox Code Playgroud)

没有通过动态对象的属性,没有自定义类,没有松散的函数,没有范围重叠.正是逻辑所期望的:你只是将参数传递给它.

要正确删除每个侦听器,您可以在以后执行此操作:

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);
}
Run Code Online (Sandbox Code Playgroud)

恕我直言,这是最简单但最可靠的方法.

  • 当然如此.它实际上是"面向安全的":函数的生命周期一直持续到你得到它的返回监听器,它的引用可以保存在一个变量中,以便向后移动.你可以控制一切. (4认同)

小智 6

这是一个例子

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);
}
Run Code Online (Sandbox Code Playgroud)