将参数传递给事件侦听器/处理程序

时间:2009-09-23 09:27:20

标签: flash actionscript-3 addeventlistener

如何通过事件侦听器传递参数/变量?我使用匿名函数相当有效地克服了这个问题;这是一个非常简单的解决方案,但在一天结束时,它闻起来像一个巨大的功能漏洞,我觉得应该本地提供。

通常情况会继续下去,但是命运会有,现在我实际上需要删除监听器,而当你使用匿名函数时这样做有点时髦。所以,我再次尝试弄清楚如何将参数传递给事件侦听器,以便只需引用该函数即可删除事件侦听器。

看起来很奇怪,我已经克服了这个问题以及,但是,我不喜欢它并厌倦了使用它。在我看来,它是代码味道。但它就像一个魅力。我将变量,对象或其他内容存储在调度MovieClip上。因此,如果我循环访问数据数组,即时生成缩略图,我只需将数据变量(通常是具有多个属性的对象)存储在实际的缩略图MovieClip中。然后我可以通过引用访问事件监听器方法中的所有数据:

event.target.data
。 在这个例子中,“data”是持有我想要的信息的变量的名称。因为当我不使用它时出现的另一个问题是,当我循环遍历数组并生成单击以查看大图像的缩略图时,索引不一致。在循环结束时,所有缩略图都将使用最后一个索引“i”打开图像。因此,如果我有一个长度为12的数组,无论你点击什么缩略图,它们都会加载第12个图像。将数据存储到MovieClip本身,创建一个永不改变的可靠引用。

这一直困扰着我一段时间。基本上我想知道的是,这是一个好的做法,那里有更好的解决方案吗?

以下是一些饮食示例。如有必要,我可以发布更详细的例子。所有示例都描绘了一个缩略图,用于在单击时加载大图像。




不使用匿名函数(问题):

tempThumb.addEventListener(MouseEvent.CLICK, loadImage);

public function loadImage(_event:MouseEvent):void  
{
    // I don't have the variable _url and preparing a hot bath with a cold blade  
}

使用匿名函数:

tempThumb.addEventListener(MouseEvent.CLICK, function(_event:MouseEvent) { loadImage("large.jpg"); } );

public function loadImage(_url:String):void  
{
    // I got the variable _url and packing away the razor blades  
}

不使用匿名函数,但使用我的臭妖精技术将数据存储到调度事件的MovieClip中

tempThumb.data = "large.jpg";

tempThumb.addEventListener(MouseEvent.CLICK, loadImage);

public function loadImage(_event:MouseEvent):void  
{
    trace(event.target.data);
    // I can access the variable  
}

我对编程术语不了解,所以我将上面的妖精技术称为。在对象中存储/隐藏变量以供以后使用/访问。它解决了我所有的问题并且工作得非常好。但是,如果有更好的方法,我想知道 方式。

8 个答案:

答案 0 :(得分:2)

如果MovieClip需要跟踪您点击时需要知道的额外信息,那么我会使用更正式的Leprechaun技术版本。

我创建了一个名为SpecialImage的新类,它扩展了MovieClip并具有存储要加载的url的属性。

根据您创建SpecialImages的方式,您可以在代码中创建它们,也可以将库中的MovieClip链接到此类。

它基本上是一个豪华的妖精,但由于信息与图像MovieClip直接相关,将它们存储在一起感觉就像是最好的。

答案 1 :(得分:2)

(我想你会想看this answer。)

关于你的怀疑,你自己感受到了:你的妖精的臭(双关语)。想象一下,它是一个Sprite而不是MovieClip。它不是动态的,因此除非执行like Richard said,否则无法添加属性。

根据您的示例,这是您希望的更好的解决方案:

tempThumb.addEventListener(MouseEvent.CLICK, loadImage("large.jpg"));

public function loadImage(_url:String):Function {
  return function(_event:MouseEvent):void {
    // Now you have both variables _url and _event here!
  }
}

但是你希望能够删除听众,所以:

var functionLoadImage:Function = loadImage("large.jpg");
tempThumb.addEventListener(MouseEvent.CLICK, functionLoadImage);

public function loadImage(_url:String):Function {
  return function(_event:MouseEvent):void {
    // Now you have both variables _url and _event here!
  }
}

//trace(tempThumb.hasEventListener(MouseEvent.CLICK));
tempThumb.removeEventListener(MouseEvent.CLICK, functionLoadImage);
//trace(tempThumb.hasEventListener(MouseEvent.CLICK));

答案 2 :(得分:1)

如果您不喜欢将数据存储在目标成员中,则可以使用所谓的“委托”。两者都不比另一个好。这主要是偏好。

以下是Delegate类(无内置内容)的示例:http://www.actionscript.org/resources/articles/205/1/The-Delegate-Class/Page1.html

如果eventdispatcher不是你自己的类,这可能是最好的主意。否则,将变量存储在您自己的类中根本不是一个坏主意。只是OOP风格。

干杯。

答案 3 :(得分:1)

是的我知道你的意思。我所做的是扩展事件,然后发送自定义事件。这样我就可以在自定义事件中创建包含必要数据的属性。看起来干净但需要一点努力。这不是理想的,但我不知道一个明显更好的方法。

答案 4 :(得分:1)

可以更好地避免使用匿名函数,因为它们会使代码变得笨拙并且有时会导致内存泄漏。如果我也负责调度事件,我会使用自定义事件,但这不是这种情况。

在这种情况下,我会将URL和影片剪辑存储在两个单独的类级别数组中并使用

var url:String = urlArray[mcArray.indexOf(event.target)];

在事件处理程序中获取URL。

并不是说在动画片段中存储数据有什么问题,但我觉得这不是一个好方法。但是,即使在他们制造困难时遵循最佳实践也不是一个好主意 - 选择权归你所有。

答案 5 :(得分:0)

您可以执行以下操作,这基本上是一种传递自定义数据的更简洁方法。

example code:
public function myCustomEvenListener(e:MouseEvent,myCustomData:Object)
{
//Do whatever you wnat with myCustomData Object here...
}
//this is the function where you add event listeners to components..
public function init():void
{
var myCustomObject:Object=new Object();
myCustomObject.url="http://xyz.com/image.jsp";
myCustomObject.anydata="You can Add anything here";

mycomponent.addEventListener(MouseEvent.CLICK,function (e:MouseEvent) : void {
                  myCustomEventListener(e,myCustomObject);
            });

}

这只是使用匿名函数的另一种方式....

答案 6 :(得分:0)

最好的做法是创建一个为您的thumnbnail扩展MovieClip的自定义类,并让该缩略图调度一个自定义Event类,该类可以存储您的数据:

制作可以将URLEvent属性与事件一起存储的自定义url

package{

import flash.events.Event;

public class URLEvent extends Event{

    public var url:String;
    public static const CLICK:String = "URLEventClick"

    public function URLEvent(type:String, url:String = "", bubbles:Boolean = false, cancelable:Boolean=false){
        super(type, bubbles, cancelable);
        this.url = url;
    }

    override public function clone():Event{
        return new URLEvent(type,url,bubbles,cancelable);
    }
  }
}

创建一个可以存储url变量的自定义缩略图类,并在单击时发送URLEvent:

package{

import flash.display.MovieClip;
import flash.events.MouseEvent;

public class Thumbnail extends MovieClip{

    protected var url:String;

    public function Thumbnail(url:String){
        this.url = url;
        addEventListener(MouseEvent.CLICK,clickHandler);
    }

    //the thumbnail captures its own click and dispatches a custom event
    protected function clickHandler(event:MouseEvent):void{
        dispatchEvent(new URLEvent(URLEvent.CLICK,url));
    }

}

现在,您可以使用Thumbnail类加载每张图片:

tempThumb.addEventListener(URLEvent.CLICK,tempThumbClickHandler);

function tempThumbClickHandler(event:URLEvent):void{
//we can get the url property direct from the URLEvent
    loadImage(event.url);
}

这种方法是更好的OOP练习,因为你不需要知道你的event.target是什么类型的对象 - 你从事件类型中确切地知道每个事件将发送什么类型的数据。

答案 7 :(得分:0)

如果我正在寻找这个功能,而且我经常这样做,我会让tempThumb成为一个带有url属性的类。然后:

MyThumbClass(event.target).url //in the MouseEvent.CLICK handler

强类型,易于访问,语法清晰,复杂度低。