as3.0中的事件Event(位於包flash.events內,繼承至Object,子類有…)
既然是釋疑,主要是在與同事聊天的過程中提及的幾個問題:
1、addEventListener重複監聽是否會被多次調用?
2、如何移除一個匿名函數的監聽?
3、target、currentTarget之間的區別
4、關於Event對象的其它需要注意的地方
/*****************************************
* addEventListener重複監聽是否會被多次調用?
******************************************/
這裏重點在於“重複”兩個字,如果監聽一個對象,事件類型相同,監聽函數也是相同,則該監聽函數在事件被觸發時只被調用一次。如果監聽的事件類型不同或是監聽函數不同,則該監聽函數,在該事件類型被觸發時調用。
上面的寫法,onClickHandler函數在對象的CLICK事件被觸發時被調用一次。
使用removeEventListener則會移除該事件,CLICK事件被觸發時不再調用onClickHandler函數。
如果監聽函數爲匿名函數:
需要移除匿名函數時,一是可以使用變量保存該匿名函數的引用,二是可以在該匿名函數內使用arguments.callee獲取該匿名函數的引用,使用removeEventListener移除對指定事件類型的監聽。
使用閉包獲得的匿名函數,每次調用時獲得的匿名函數都不是同一個引用,所以對事件的監聽將會被多次調用。例如有一個函數爲:getClickFn()。
當多次使用該函數進行監聽時,將會被多次調用。
而addEventListener方法,屬於類EventDispatcher(flash.events,繼承至Object,實現IEventDispatcher),子類有(DisplayObject…)
該方法有5個參數。addEventListener(eventType, listenerFn, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false);
一般很少用到後面的參數,分別是:
useCapture –> 是否在捕獲階段監聽事件,默認在冒泡階段進行監聽
priority –> 默認爲0,也就是監聽事件時,回調監聽函數的“層次”順序,比如之後監聽的函數要在事件觸發時有攔截操作等(取消事件冒泡,阻止其後事件的觸發stopPropagation、stopImmediatePropagation)
useWeakReference –> 是否爲弱引用,強烈建議避免使用該參數,不易控制。
hasEventListener用來檢查對象是否爲特定的事件類型註冊了監聽器。
/*****************************************
* target、currentTarget的區別
******************************************/
這個是比較容易混淆,但也非常常見。一句話概括來講就是:
target -- 觸發事件的事件源,currentTarget -- 觸發事件的監聽對象。
/*****************************************
* 關於Event其它要注意的地方
******************************************/
首先要很清楚,一個事件它經歷了哪幾個階段:捕獲階段 –> 目標階段 –> 冒泡階段
然後就是stopPropagation、stopImmediatePropagation這兩個方法它們的區別,寫個例子就知道了<從方法的說明中就能知道大概意思,寫個Demo加深印象就可以了>
寫了一堆,最後還是寫一個demo,比較實際一點:
1: package 2: { 3: import flash.display.MovieClip; 4: import flash.display.Sprite; 5: import flash.events.MouseEvent; 6: import flash.filters.GlowFilter; 7: import flash.text.TextField; 8: import flash.text.TextFieldAutoSize; 9: import flash.text.TextFieldType; 10: import flash.text.TextFormat; 11: /** 12: * ... 13: * @author Meteoric 14: */ 15: public class EventDemo extends Sprite 16: { 17: 18: public function EventDemo() 19: { 20: initView(); 21: } 22: 23: private var txt:TextField; 24: 25: private function getTextGlowFilter(colorVal:uint=0x000000, blur:Number=2):GlowFilter 26: { 27: var color:uint = colorVal; 28: var alpha:Number = 1; 29: var blurX:Number = blur; 30: var blurY:Number = blur; 31: var strength:Number = 255; 32: var quality:Number = 1; 33: 34: return new GlowFilter(color, alpha, blurX, blurY, strength, quality); 35: } 36: 37: private function initView():void 38: { 39: txt = new TextField(); 40: txt.x = 200; 41: txt.y = 50; 42: txt.selectable = false; 43: txt.mouseEnabled = false; 44: txt.autoSize = TextFieldAutoSize.LEFT; 45: txt.width = 350; 46: //txt.height = 100; 47: txt.wordWrap = true; 48: txt.multiline = true; 49: txt.type = TextFieldType.INPUT; 50: txt.background = true; 51: txt.backgroundColor = 0x232323; 52: 53: var txtfor:TextFormat = new TextFormat(); 54: txtfor.size = 15; 55: txtfor.font = "verdana"; 56: txtfor.bold = true; 57: txtfor.color = 0xffffff; 58: 59: txt.defaultTextFormat = txtfor; 60: txt.filters = [getTextGlowFilter(0xffcc66)]; 61: 62: addChild(txt); 63: 64: //監聽事件 65: var mc:MovieClip = new MovieClip(); 66: 67: mc.graphics.clear(); 68: mc.graphics.beginFill(0xcc0000, .7); 69: mc.graphics.drawCircle(100, 100, 50); 70: mc.graphics.endFill(); 71: 72: addChild(mc); 73: 74: mc.buttonMode = true; 75: 76: 77: //重複的監聽只會被調用一次 78: mc.addEventListener(MouseEvent.CLICK, onClickHandler); 79: mc.addEventListener(MouseEvent.CLICK, onClickHandler); 80: mc.addEventListener(MouseEvent.CLICK, onClickHandler); 81: 82: //檢測是否綁定了指定的事件 83: setTxt('是否監聽了MouseEvent.CLICK事件:' + mc.hasEventListener(MouseEvent.CLICK)); 84: 85: //移除指定的監聽事件 86: mc.removeEventListener(MouseEvent.CLICK, onClickHandler); 87: 88: //重複監聽的事件,移除一次後將不再被監聽 89: setTxt('是否監聽了MouseEvent.CLICK事件:' + mc.hasEventListener(MouseEvent.CLICK)); 90: 91: //使用匿名函數進行事件的監聽 92: mc.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void { 93: var _mc:MovieClip = e.target as MovieClip; 94: _mc.removeEventListener(MouseEvent.CLICK, arguments.callee); 95: 96: setTxt('~~haha~~我就是匿名函數【remove】'); 97: }); 98: 99: //下面使用getClickFn獲得的是兩個不同的匿名函數引用 100: mc.addEventListener(MouseEvent.CLICK, getClickFn(100, function(fn:Function, evt:MouseEvent):void { 101: 102: var _mc:MovieClip = evt.target as MovieClip; 103: 104: _mc.removeEventListener(MouseEvent.CLICK, fn); 105: 106: setTxt("~~hehe~~另外一個匿名函數【remove】"); 107: 108: }), false, 1); 109: 110: mc.addEventListener(MouseEvent.CLICK, getClickFn(50)); 111: } 112: 113: private function onClickHandler(e:MouseEvent):void 114: { 115: setTxt("----onClickHandler" + getNow()); 116: } 117: 118: private function getClickFn(n:Number=0, fn:Function=null):Function 119: { 120: var num:Number = n; 121: 122: return function(evt:MouseEvent):void { 123: fn && fn(arguments.callee, evt); 124: 125: setTxt('當前num的值:' + (++num)); 126: } 127: } 128: 129: private function getNow():String 130: { 131: var date:Date = new Date(); 132: var year:Number = date.getFullYear(); 133: var month:Number = date.getMonth() + 1; 134: var day:Number = date.getDay(); 135: 136: var hours:Number = date.getHours(); 137: var minutes:Number = date.getMinutes(); 138: var seconds:Number = date.getSeconds(); 139: 140: return [year, month, day].join("-") + " " + [hours, minutes, seconds].join(":"); 141: } 142: 143: private function setTxt(str:String):void 144: { 145: txt.appendText(str + '\n'); 146: 147: trace(str); 148: } 149: 150: } 151: 152: }