[6.建立強(qiáng)大的事件處理機(jī)制]
這一節(jié)講建立強(qiáng)大的事件處理機(jī)制.學(xué)完這節(jié),如果有接觸過(guò) AS3 的,馬上會(huì)想到一句:這不就是 AS3 的事件處理機(jī)制嗎? 的確.可以說(shuō)跟 AS3 的事件處理機(jī)制一模一樣.但還是有個(gè)作用域的問(wèn)題.這節(jié)對(duì)想學(xué)習(xí) AS3 的事件處理機(jī)制會(huì)有很大 幫助.如果你掌握這節(jié)中的內(nèi)容,在 AS3 中就只有語(yǔ)法問(wèn)題.也就會(huì)很快進(jìn)入狀態(tài).畢竟是"水往低處流,人往高處走".對(duì)現(xiàn) 在用 AS2 的,學(xué) AS3 是遲早的問(wèn)題.不過(guò) AS2 在新版本出來(lái)之前還是會(huì)很有用的(個(gè)人的看法).
作用域因?yàn)橐粯?前面也講過(guò),這里就不在啰嗦. 事件對(duì)象.這里已經(jīng)創(chuàng)建一個(gè) Event 類(或其子類)來(lái)代替.但功能一樣.
這節(jié)講的事件處理機(jī)制的形態(tài)(代碼). 發(fā)送事件:
//繼承. import AS2.events.Event; import AS2.events.CFEventDispatcher; class className extends CFEventDispatcher { ... this.dispatchEvent(new Event(Event.COMPLETE)); ... } 或
//不繼承. import AS2.events.Event; import AS2.events.CFEventDispatcher; class className { public var addEventListener:Function; public var removeEventListener:Function; private var dispatchEvent:Function; public function className() { //此方法要在使用 dispatchEvent 方法前被執(zhí)行.一般放于構(gòu)造函數(shù)中. CFEventDispatcher.initialize(this); } ... this.dispatchEvent(new Event(Event.COMPLETE)); ... } 偵聽事件:
//使用自定義函數(shù). import AS2.events.Event; import className; ... var cn:className = new className(); //自定義函數(shù). function completeHandler(evt:Event):Void { trace(this); //輸出: _level0.cn } cn.addEventListener(Event.COMPLETE, completeHandler); ... 或
//使用事件偵聽器對(duì)象. import AS2.events.Event; import className; ... var cn:className = new className(); //事件同名函數(shù). function complete(evt:Event):Void { trace(this); //輸出: this(指向偵聽器對(duì)象) } cn.addEventListener(Event.COMPLETE, this); ... 移除偵聽:
//使用自定義函數(shù). ... cn.removeEventListener(Event.COMPLETE, completeHandler); ... 或
//使用事件偵聽器對(duì)象. ... cn.removeEventListener(Event.COMPLETE, this); ... AS2.utils.CFDelegate; AS2.events.Event; AS2.events.CFEventDispatcher; 這些是什么?下面講解:
[6.1.創(chuàng)建 CFDelegate 類(修改 Delegate 類)] CFDelegate 類是 Delegate 類的修改版本.簡(jiǎn)化了代碼(一般不用的功能).提高了執(zhí)行效率.
此類文檔詳細(xì): Classes/AS2/utils/CFDelegate.as
主類: 打開 CFDelegate.as 文檔.輸入下面的代碼:
class AS2.utils.CFDelegate { public static function create(scope:Object, method:Function):Function { var f:Function = function () { method.apply(scope, arguments); }; return f; } } 保存文檔.
[6.2.創(chuàng)建 CFEventDispatcher 類(修改 EventDispatcher 類)] CFEventDispatcher 類是 EventDispatcher 類的修改版本.簡(jiǎn)化了代碼(一般不用的功能).提高了執(zhí)行效率.
此類文檔詳細(xì): Classes/AS2/events/CFEventDispatcher.as
主類: 打開 CFEventDispatcher.as 文檔.輸入下面的代碼:
*/ //---------------------------------------- class AS2.events.CFEventDispatcher { //---------------------------------------- //構(gòu)造函數(shù) public function CFEventDispatcher(){} //---------------------------------------- //當(dāng)不繼承此類時(shí),此屬性才有效. private static var _ed:CFEventDispatcher; //---------------------------------------- private static function _removeEventListener(queue:Object, handler):Void { /* 這里主要用于刪除事件數(shù)組中的事件處理器. */ if (queue != undefined) { var l:Number = queue.length; while(l--){ if(queue[l] == handler){ queue.splice(l, 1); return; } } } } //當(dāng)不繼承此類時(shí).此方法有效. public static function initialize(o:Object):Void { /* 如果沒(méi)有繼承此類,而是使用 initialize 此方法時(shí), _ed 等于 undefined.然后創(chuàng)建此類的實(shí)例. 最后將事件通知和偵聽器管理功能添加到 initialize 方法中的對(duì)象 o. 前面所講的不繼承此類時(shí)需添加的三個(gè)方法,其實(shí)是四個(gè).還有 dispatchQueue 方法.但此方法在 調(diào)用 dispatchEvent 方法時(shí)就會(huì)自動(dòng)調(diào)用.可能有人會(huì)問(wèn),為什么沒(méi)有定義就能調(diào)用?因?yàn)樵诤瘮?shù) 中可以操作對(duì)象.從而對(duì)對(duì)象動(dòng)態(tài)添加方法和屬性.這里就是用了在函數(shù)中操作對(duì)象. */ if (_ed == undefined) { _ed = new CFEventDispatcher(); } o.addEventListener = _ed.addEventListener; o.removeEventListener = _ed.removeEventListener; o.dispatchEvent = _ed.dispatchEvent; o.dispatchQueue = _ed.dispatchQueue; } //---------------------------------------- private function dispatchQueue(queueObj:Object, eventObj:Object):Void { /* 這里主要用于判斷事件處理器是對(duì)象還是函數(shù). */ if (queueObj[eventObj.type] != undefined) { for (var i:String in queueObj[eventObj.type]) { var o = queueObj[eventObj.type][i]; if (typeof (o) == "object" || typeof (o) == "movieclip") { //調(diào)用對(duì)象中的handleEvent函數(shù). //if (o.handleEvent != undefined) { //o.handleEvent(eventObj); //} //調(diào)用對(duì)象中的事件同名函數(shù). //if (o[eventObj.type] != undefined) { o[eventObj.type](eventObj); //} } else { //調(diào)用自定義函數(shù). o.apply(queueObj, [eventObj]); } } } } public function dispatchEvent(eventObj:Object):Void { //將事件源始終指向this(應(yīng)用此類的對(duì)象). eventObj.target = this; //此句對(duì)動(dòng)態(tài)類,或在類中定義"事件名Handler" 這樣的函數(shù)時(shí)才有效.在這里我注釋了這句.你如果你想用,可以啟用它. /* 用法: 對(duì)象.事件名Handler = function(evt:Object){}; */ //this[eventObj.type + "Handler"](eventObj); this.dispatchQueue(this, eventObj); } public function addEventListener(event:String, handler):Void { //這里可以這樣理解: /* 使用 addEventListener("click", 事件處理器); 添加事件. 這時(shí), this["click"] 就等于 undefined. (this["click"] == undefined) = true 然后將創(chuàng)建一個(gè)新數(shù)組來(lái)存儲(chǔ)事件處理器. this["click"] = []; 然后執(zhí)行 CFEventDispatcher._removeEventListener(this["click"], 事件處理器); 來(lái)檢測(cè)此事件是否有相同的事件處理器.如果是就刪除它. 舉個(gè)例:當(dāng)你在一個(gè)網(wǎng)站注冊(cè)用戶名時(shí).網(wǎng)站的注冊(cè)程序會(huì)從數(shù)據(jù)庫(kù)中檢測(cè)是否有與你相同的用戶名. 如果有將會(huì)提示你重新輸入用戶名(在這里就是直接刪除了).如果沒(méi)有就會(huì)注冊(cè)成功(這里就在后面 執(zhí)行 push).但是網(wǎng)站的注冊(cè)程序不會(huì)從數(shù)據(jù)庫(kù)中檢測(cè)是否有與你相同的密碼. 就是說(shuō)一個(gè)事件,可添加多個(gè)不同的事件處理器,但不能添加相同的事件處理器. 當(dāng)添加新的事件時(shí),也是一樣的 最后使用 this["click"].push(事件處理器); 將事件處理器添加到事件數(shù)組. */ if (this[event] == undefined) { this[event] = new Array(); } //ASSetPropFlags 是隱藏的方法.用它和不用它貌似沒(méi)有區(qū)別.大家可以研究下. //_global.ASSetPropFlags(this, event, 1); CFEventDispatcher._removeEventListener(this[event], handler); this[event].push(handler); } public function removeEventListener(event:String, handler):Void { //這里我就不啰嗦了. CFEventDispatcher._removeEventListener(this[event], handler); } //---------------------------------------- } 保存文檔.
[6.3.創(chuàng)建 Event 類(事件基類,繼承 Object 類)] 你可以把它看作事件對(duì)象.因應(yīng)它的工作就是生成事件對(duì)象.
此類文檔詳細(xì): Classes/AS2/events/Event.as
主類: 打開 Event.as 文檔.輸入下面的代碼:
class AS2.events.Event extends Object { //---------------------------------------- //事件的常數(shù)名. public static var COMPLETE:String = "complete"; public static var CANCEL:String = "cancel"; public static var CHANGE:String = "change"; public static var CLOSE:String = "close"; public static var CONNECT:String = "connect"; public static var FULLSCREEN:String = "fullScreen"; public static var OPEN:String = "open"; public static var REMOVED:String = "removed"; public static var RESIZE:String = "resize"; public static var SCROLL:String = "scroll"; public static var SELECT:String = "select"; //---------------------------------------- public var type:String; public var target:Object; //---------------------------------------- private var className:String = "Event"; //---------------------------------------- //構(gòu)造函數(shù). public function Event(type:String) { this.type = type; } //---------------------------------------- public function toString():String { var str:String = ""; for (var i:String in this) { if (this[i] != undefined) { str += i + "=" + this[i] + " "; } } return "[" + this.className + " " + str.slice(0,str.length - 1) + "]"; } //---------------------------------------- } 保存文檔.
此類包含下面內(nèi)容: 1.事件的常數(shù)名.如:
public static var COMPLETE:String = "complete"; ... 2.基本的屬性.如:
public var type:String; ... 3.className 屬性.如:
private var className:String = "Event"; 4.構(gòu)造函數(shù).如:
public function Event(type:String) { this.type = type; } 5.toString() 方法.如:
public function toString():String { var str:String = ""; for (var i:String in this) { if (this[i] != undefined) { str += i + "=" + this[i] + " "; } } return "[" + this.className + " " + str.slice(0,str.length - 1) + "]"; }
如果你嫌此方法阻礙你的執(zhí)行效率.可以改成如下(標(biāo)準(zhǔn)):
public function toString():String { return "[object " + this.className + "]"; } 這里講下 toString() 方法.在類中定義此方法.在輸出此類實(shí)例名實(shí)調(diào)用此方法.如:
class className { ... private var className:String = "className"; public function toString():String { return "[object " + this.className + "]"; } ... }
import className; var cn:className = new className(); trace(cn);// 調(diào)用 toString() 方法.輸出: [object className] 當(dāng)然你也可以改成 AS3 中 Event 類一樣的方法.但沒(méi)有必要,很少會(huì)用到. 如果要向 Event 類傳遞參數(shù)和定義新的事件名,請(qǐng)看下面.
[6.4.創(chuàng)建 IOErrorEvent 類(錯(cuò)誤事件類,繼承 Event 類)] 此類文檔詳細(xì): Classes/AS2/events/IOErrorEvent.as
主類: 打開 IOErrorEvent.as 文檔,輸入下面的代碼:
import AS2.events.Event; //---------------------------------------- class AS2.events.IOErrorEvent extends Event { //---------------------------------------- //事件的常數(shù)名. public static var IO_ERROR:String = "IOError"; //---------------------------------------- //屬性參數(shù). public var text:String; //---------------------------------------- //className 屬性 private var className:String = "IOErrorEvent"; //---------------------------------------- //在構(gòu)造函數(shù)中添加參數(shù). public function IOErrorEvent(type:String, text:String) { super(type); this.text = text; } //---------------------------------------- } 保存文檔.
[6.5.創(chuàng)建 HTTPStatusEvent 類(http狀態(tài)事件類,繼承 Event 類)] 此類文檔詳細(xì): Classes/AS2/events/HTTPStatusEvent.as
主類: 打開 HTTPStatusEvent.as 文檔.輸入下面的代碼:
import AS2.events.Event; //---------------------------------------- class AS2.events.HTTPStatusEvent extends Event { //---------------------------------------- //事件的常數(shù)名. public static var HTTP_STATUS:String = "httpStatus"; //---------------------------------------- //屬性參數(shù). public var status:Number; //---------------------------------------- //className 屬性 private var className:String = "HTTPStatusEvent"; //---------------------------------------- //在構(gòu)造函數(shù)中添加參數(shù). public function HTTPStatusEvent(type:String, status:Number) { super(type); this.status = status; } //---------------------------------------- } 保存文檔.
[6.6.示例: EventClass 類(簡(jiǎn)單的示例)] 此示例文檔詳細(xì): Example/AS2/events/Event/EventClass.as Example/AS2/events/Event/EventExample.as Example/AS2/events/Event/EventExample.xml Example/AS2/events/Event/EventExample.fla
主類: 打開 EventClass.as 文檔.輸入下面的代碼:
import AS2.utils.CFDelegate; import AS2.events.Event; import AS2.events.IOErrorEvent; import AS2.events.HTTPStatusEvent; import AS2.events.CFEventDispatcher; //---------------------------------------- class EventClass extends CFEventDispatcher { //---------------------------------------- public var tXML:XML; //---------------------------------------- public function EventClass(url:String) { this.tXML = new XML(); this.tXML.onLoad = CFDelegate.create(this, this.XMLonLoad); this.tXML.onHTTPStatus = CFDelegate.create(this, this.XMLHTTPStatus); this.tXML.load(url); } public function toString():String { return "[EventClass]"; } //---------------------------------------- private function XMLonLoad(success:Boolean):Void { if (success) { this.dispatchEvent(new Event(Event.COMPLETE)); } else { this.dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, "加載錯(cuò)誤!請(qǐng)檢查 XML 文檔地址和網(wǎng)絡(luò)連接")); } } private function XMLHTTPStatus(httpStatus:Number):Void { this.dispatchEvent(new HTTPStatusEvent(HTTPStatusEvent.HTTP_STATUS, httpStatus)); } //---------------------------------------- } 保存文檔.
示例類: 打開 EventExample.as 文檔.輸入下面的代碼(手指應(yīng)該很痛吧.呵.我也一樣.(可能是無(wú)謂的話)):
import EventClass; import AS2.events.Event; import AS2.events.IOErrorEvent; import AS2.events.HTTPStatusEvent; //---------------------------------------- class EventExample { public function EventExample() { var ee:EventClass = new EventClass("http://localhost/Examples/AS2/events/Event/EventExample.xml"); ee.addEventListener(Event.COMPLETE, this.completeHandler); ee.addEventListener(IOErrorEvent.IO_ERROR, this.ioErrorHandler); ee.addEventListener(HTTPStatusEvent.HTTP_STATUS, this.httpStatusHandler); } private function completeHandler(evt:Event):Void { trace(evt); } private function ioErrorHandler(evt:IOErrorEvent):Void { trace(evt); } private function httpStatusHandler(evt:HTTPStatusEvent):Void { trace(evt); } } 保存文檔. 這里注意 XML 文檔地址不是本地地址,是用服務(wù)器地址的(測(cè)試 http 狀態(tài)用):
var ee:EventClass = new EventClass("http://localhost/Examples/AS2/events/Event/EventExample.xml"); 要加載的 XML 文檔: 打開 EventExample.xml 文檔,隨便輸入一些內(nèi)容便可.測(cè)試用.
示例 fla 文檔: 打開 EventExample.fla 文檔.將"圖層 1"重命名為 Actions.并在第一幀中輸入下面的代碼:
new EventExample(); 保存文檔. 測(cè)試 Flash 文檔.在 XML 文檔成功加載后會(huì)在輸出面板中顯示以下內(nèi)容:
[HTTPStatusEvent target=[EventClass] status=200 type=httpStatus] [Event target=[EventClass] type=complete] 當(dāng)將 XML 地址改成錯(cuò)誤時(shí),在輸出面板中將顯示以下內(nèi)容:
Error opening URL "http://localhost/Example/AS2/events/Event/EventExamples.xml" [HTTPStatusEvent target=[EventClass] status=404 type=httpStatus] [IOErrorEvent target=[EventClass] text=加載錯(cuò)誤!請(qǐng)檢查 XML 文檔地址和網(wǎng)絡(luò)連接 type=IOError] 下面再看一個(gè)示例: [6.7.示例: Timer 類(定時(shí)器,功能跟 AS3 中的 Timer 類一樣)] 此示例文檔詳細(xì): Classes/AS2/utils/Timer.as Classes/AS2/utils/TimerEvent.as Example/AS2/utils/Timer/TimerExample.as Example/AS2/utils/Timer/TimerExample.fla
主類: 打開 Timer.as 文檔,輸入下面的代碼:
import AS2.utils.TimerEvent; import AS2.utils.CFDelegate; import AS2.events.CFEventDispatcher; //---------------------------------------- class AS2.utils.Timer extends CFEventDispatcher { //---------------------------------------- private var _timerID:Number; private var _delay:Number; private var _repeatCount:Number; private var _currentCount:Number = 0; private var _running:Boolean; //---------------------------------------- /* @parameter delay: 延遲,單位毫秒. @parameter repeatCount: 重復(fù)次數(shù).默認(rèn)為Infinity(正無(wú)窮大); */ public function Timer(delay:Number, repeatCount:Number) { if (isNaN(delay)) { return; } if (isNaN(repeatCount)) { repeatCount = Infinity; } this._delay = delay; this._repeatCount = repeatCount; } //---------------------------------------- public function reset():Void { this._currentCount = 0; this.stop(); } public function start():Void { this._timerID = setInterval(CFDelegate.create(this, this.startTimer), this._delay); this._running = true; } public function stop():Void { clearInterval(this._timerID); this._running = false; } public function toString():String { return "[Timer]"; } //---------------------------------------- private function startTimer():Void { this._currentCount++; this.dispatchEvent(new TimerEvent(TimerEvent.TIMER, this._currentCount)); if (this._currentCount == this._repeatCount) { this.reset(); this.dispatchEvent(new TimerEvent(TimerEvent.TIMER_COMPLETE)); } } //---------------------------------------- public function get delay():Number { return this._delay; } public function set delay(d:Number):Void { this._delay = d; } public function get repeatCount():Number { return this._repeatCount; } public function set repeatCount(r:Number):Void { this._repeatCount = r; } public function get currentCount():Number { return this._currentCount; } public function get running():Boolean { return this._running; } //---------------------------------------- } 保存文檔.
Timer 事件類: 打開 TimerEvent.as 文檔,輸入下面的代碼:
import AS2.events.Event; //---------------------------------------- class AS2.utils.TimerEvent extends Event { //---------------------------------------- public static var TIMER:String = "timer"; public static var TIMER_COMPLETE:String = "timerComplete"; //---------------------------------------- public var currentCount:Number; //---------------------------------------- private var className:String = "TimerEvent"; //---------------------------------------- public function TimerEvent(type:String, currentCount:Number) { super(type); this.currentCount = currentCount; } //---------------------------------------- } 保存文檔.
示例類: 打開 TimerExample.as 文檔,輸入下面的代碼:
import AS2.utils.Timer; import AS2.utils.TimerEvent; //---------------------------------------- class TimerExample { //---------------------------------------- public function TimerExample() { var te:Timer = new Timer(1000, 5); te.addEventListener(TimerEvent.TIMER, this.timerHandler); te.addEventListener(TimerEvent.TIMER_COMPLETE, this.timerCompleteHandler); te.start(); } private function timerHandler(evt:TimerEvent):Void { trace("timer: " + evt); } private function timerCompleteHandler(evt:TimerEvent):Void { trace("timerComplete: " + evt); } //---------------------------------------- } 保存文檔.
示例 fla 文檔: 打開 TimerExample.fla 文檔,將"圖層 1"重命名為 Actions.并在第一幀中輸入下面的代碼:
new TimerExample(); 保存文檔. 測(cè)試 Flash 文檔.在輸出面板可以看到下面的內(nèi)容:
timer: [TimerEvent target=[Timer] currentCount=1 type=timer] timer: [TimerEvent target=[Timer] currentCount=2 type=timer] timer: [TimerEvent target=[Timer] currentCount=3 type=timer] timer: [TimerEvent target=[Timer] currentCount=4 type=timer] timer: [TimerEvent target=[Timer] currentCount=5 type=timer] timerComplete: [TimerEvent target=[Timer] type=timerComplete]
經(jīng)典論壇討論: http://bbs.blueidea.com/thread-2768209-1-1.html
出處:藍(lán)色理想
責(zé)任編輯:藍(lán)色月光
上一頁(yè) [AS2]事件處理機(jī)制 -- 使用addListener方法 二 下一頁(yè) [AS2]事件處理機(jī)制 -- 小結(jié)
◎進(jìn)入論壇Flash專欄版塊參加討論
|