event.preventDefault对我来说不清楚,即使我理解stopImmediatePropagation和stopPropagation

时间:2016-10-29 09:12:16

标签: events mouseevent actionscript-3

似乎很难理解event.preventDefault。(这是AS3的黑暗面)。 :)

stopImmediatePropagation - stopPropagation方法很容易理解。 这是我做的一个测试(只需要在时间线上复制/粘贴),这可以避免你花太多时间。

我只是不明白在哪种情况下,preventDefault可能有用...... 如果您有一些建议或链接,请给我一些反馈意见吗?

以下是代码:

// This example is coded on the Timeline.
// The Stage must fit 550 * 400 pixels (default size).
import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;

// function to create a MovieClip and return it to a variable.
function createMC(target:DisplayObjectContainer):MovieClip{
    var mc:MovieClip = new MovieClip();
    target.addChild(mc);
    return mc;
}
// function that draws a Rectangle in the MovieClip of your choice.
function dRect(target:MovieClip,x:uint,y:uint,width:uint,height:uint,color:uint,alpha:Number):void{
    var g:Graphics = target.graphics;
    g.lineStyle(1,0x000000);
    g.beginFill(color,alpha);
    g.drawRect(x-width/2,y-height/2,width,height);
    g.endFill();
}
// event function that trace the properties of the Event.
function traceTarget(me:MouseEvent):void{
    trace(" *** event.phase = " + me.eventPhase + ", event.bubbles = " + me.bubbles);
    trace("me.target.name = " + me.target.name);
    trace("me.currentTarget.name(the listening object) = " + me.currentTarget.name);
    /*
    Use preventDefault and the events  for m1 AND this will be triggered.
    MOUSE_DOWN,setText will be called 2 times 1 time for this, the second time for m1!
    MOUSE_DOWN,traceTarget will be called 2 times 1 time for this, the second time for m1!
    */
    //me.preventDefault();
    /*
    Use stopPropagation to avoid that the same function is not called if an event occurs.
    MOUSE_DOWN,setText will be called !
    */
    me.stopPropagation();
    /*
    Use stopImmediatePropagation to avoid all the functions that another listener may trigger.
    MOUSE_DOWN,setText WILL NEVER BE CALLED because traceTarget has been called!
    stopImmediatePropagation will only allow the first listener (traceTarget).
    */
    //me.stopImmediatePropagation();
    trace(me.toString());
    // trace the Event that is triggered.
}
function setText(me:MouseEvent):void{
    tf_1.text = "me.target.name = " + me.target.name;
    tf_1.setTextFormat(tf);
    countText++;
    trace("setText("+ me.target + ") has been called " + countText + " time(s)");
    countText = 0;
}
/*
A counter to see how many times an Event method is triggered
*/
var countText:uint = 0;
/*
Declare a TextField
*/
var tf_1:TextField = new TextField();
this.addChild(tf_1);
tf_1.width = 300;
tf_1.height = 20;
tf_1.x = this.stage.stageWidth - this.stage.stageWidth/2 - tf_1.width/2;
tf_1.y = 30;
var tf:TextFormat = new TextFormat(null,16,0xff0000,true,null,null,null,null,TextFormatAlign.CENTER)
tf_1.text = "Click on a Square/Rectangle";
tf_1.setTextFormat(tf);
/*
Declare 4 MovieClips
3 MovieClips inside each other
    - m1 on "this" (root1 in this case).
    - m2 inside m1
    - m3 inside m2
1 MovieClip on "this" (root1 in this case).
*/
var m1:MovieClip
var m2:MovieClip
var m3:MovieClip
var otherClip:MovieClip
// Create the MovieClips
m1 = createMC(this);
m2 = createMC(m1);
m3 = createMC(m2);
otherClip = createMC(this);
// set the names for the MovieClip's
m1.name = "movieClip_1";
m2.name = "movieClip_2";
m3.name = "movieClip_3";
otherClip.name = "otherClip";
// Draw Rectangles in the MovieClip's
dRect(m1,275,200,100,100,0xff0000,1);
dRect(m2,275,200,50,50,0x00ff00,1);
dRect(m3,275,200,25,25,0x0000ff,1);
dRect(otherClip,100,200,50,50,0xff9900,1);
// Add a listener on m1 MovieClip.
m1.addEventListener(MouseEvent.MOUSE_DOWN,traceTarget,false);
m1.addEventListener(MouseEvent.MOUSE_DOWN,setText,false);
//  Add a listener on root (root1 in this case).
this.addEventListener(MouseEvent.MOUSE_DOWN,traceTarget,false);
this.addEventListener(MouseEvent.MOUSE_DOWN,setText,false);

如果你能帮助我理解preventDefault方法,我应该非常高兴。

祝你好运。尼古拉斯。

2 个答案:

答案 0 :(得分:2)

来自documentation of preventDefault()

  

许多事件都有默认执行的关联行为。例如,如果用户在文本字段中键入字符,则默认行为是字符显示在文本字段中。由于可以取消TextEvent.TEXT_INPUT事件的默认行为,因此您可以使用preventDefault()方法来阻止该字符出现。

以下是一个例子:

package 
{
    import flash.text.TextField;
    import flash.text.TextFieldType;
    import flash.display.Sprite;
    import flash.events.TextEvent;

    public class Main extends Sprite 
    {
        public function Main() 
        {
            var tf:TextField = new TextField();
            tf.type = TextFieldType.INPUT;
            tf.border = true;
            addChild(tf);

            tf.addEventListener(TextEvent.TEXT_INPUT, onInput);         
        }

        private function onInput(te:TextEvent):void
        {
            te.preventDefault();
        }
    }
}

TextField就在那里,但你不能输入它。如果您注释掉添加侦听器的行,则默认行为不会被阻止,您可以键入。

stopImmediatePropagation()stopPropagation()eventPhase都关注事件流程:捕获,定位和冒泡的三个阶段。因此,它们可用于影响Event"是否达到"为其添加侦听器的对象。如果您想将为事件添加的侦听器视为自定义行为,可以调用上面的三个" preventCustom()"。

这两种方法的文档明确提到了这一点:

  

注意:此方法不会取消与此事件关联的行为;有关该功能,请参阅preventDefault()

preventDefault()处理与事件关联的默认行为,与事件流无关。

作为一个例子,你可能会认为你可以通过在stage为捕获阶段添加一个监听器然后停止传播来实现与上面例子相同的事情,如下所示:

package 
{
    import flash.text.TextField;
    import flash.text.TextFieldType;
    import flash.display.Sprite;
    import flash.events.TextEvent;

    public class Main extends Sprite 
    {
        public function Main() 
        {
            var tf:TextField = new TextField();
            tf.type = TextFieldType.INPUT;
            tf.border = true;
            addChild(tf);

            stage.addEventListener(TextEvent.TEXT_INPUT, onInput, true);  // new: added to stage and for capturing phase  
        }

        private function onInput(te:TextEvent):void
        {
            te.stopImmediatePropagation(); // new: stopping propagation
        }
    }
}

如果您执行此代码,您可以输入TextField就好了。同样,您只是在这里搞乱事件流,而不是默认行为。您所做的只是阻止后续侦听器获取Event,例如,如果您向TextField本身添加一个侦听器,如下所示,它将永远不会被执行,因为您之前停止了事件流它到了。

package 
{
    import flash.text.TextField;
    import flash.text.TextFieldType;
    import flash.display.Sprite;
    import flash.events.TextEvent;

    public class Main extends Sprite 
    {
        public function Main() 
        {
            var tf:TextField = new TextField();
            tf.type = TextFieldType.INPUT;
            tf.border = true;
            addChild(tf);

            tf.addEventListener(TextEvent.TEXT_INPUT, onTfInput);
            stage.addEventListener(TextEvent.TEXT_INPUT, onInput, true);         
        }

        private function onTfInput(te:TextEvent):void
        {
            // never executed
        }

        private function onInput(te:TextEvent):void
        {
            te.stopImmediatePropagation();
        }
    }
}

tl,dr;

如果你发现一个带有自拍定时器的炸弹,stopImmediatePropagation()会阻止其他人注意到这一点,并可能防止恐慌,但只有preventDefault()才能挽救你的生命。如果cancelablefalse,则最好运行。

答案 1 :(得分:2)

来自as3文档:preventDefault()“如果可以取消该行为,则取消事件行为”。

我可以给你的一个例子是android后退按钮。如果按后退按钮,默认情况下它将最小化AIR应用程序。但如果你听它并调用preventDefault()。它将停止该默认行为,以便您可以导航到上一个打开的页面。

另一个例子是android上的主页按钮,你可以调用preventDefault()但是这个动作不能被取消,所以它会被忽略。

像你的例子一样的鼠标事件,我无法测试究竟是什么