论坛交流
首页办公自动化| 网页制作| 平面设计| 动画制作| 数据库开发| 程序设计| 全部视频教程
应用视频: Windows | Word2007 | Excel2007 | PowerPoint2007 | Dreamweaver 8 | Fireworks 8 | Flash 8 | Photoshop cs | CorelDraw 12
编程视频: C语言视频教程 | HTML | Div+Css布局 | Javascript | Access数据库 | Asp | Sql Server数据库Asp.net  | Flash AS
当前位置 > 文字教程 > Flash AS编程教程
Tag:2.0,3.0菜鸟,游戏,,cs,技巧,源码,,文本,文字,函数,音乐,随机,拖拽,asp,access,xml,mc,视频教程

类定义方法中的事件处理范围

文章类别:Flash AS编程 | 发表日期:2008-10-6 18:06:47


原文 senocular.com

Frank翻译
第一次翻那么长的文章,累死了,有很多句子翻得不够理想,大家最好结合着原文看.有什么没翻好的地方产生了误导,本人不负责......

也许对与大多数as2.0的使用者来说,控制类的控制范围是比较大的问题之一.更明确的说,我指的是当对象不属于类里面的实例时,类中的方法对对象时间的控制.你可能认为那只要在类里面定义就可以存取类中实例的成员了.然而,未必属于对象的函数就属于类了.AS2.0类中的XML onLoad问题.这可能是人们使用2.0的XML时遇到的比较大的问题.这于xml并没有很大关系,但是和类中类似onLoad的反馈的事件控制有比较大的关系:
问题就在于,如果你是在类中定义的onLoad事件,onLoad脚本却未必能存取类中的属性.举例:

class XMLContentLoader { 
public var target_txt:TextField; 
private var _xml:XML; 
function XMLContentLoader(url:String, target:TextField){ 
target_txt = target; 
_xml = new XML(); 
_xml.ignoreWhite = true; 
_xml.onLoad = function(success){ 
if (success) target_txt.text = this.firstChild.toString(); 

_xml.load(url); 

}

这里,这个XMLContentLoader类创建了实例来下载xml并且在根据target_txt的属性指向的文本展示它的首节点.问题出现了,这里的onLoad不能准确的读取target_txt的属性.为什么?原因是一旦你进入了onLoad方法,你就不在类的范围中了,而是在XML实例的范围中.在这个范围中,如果要存取target_txt,其实你是在XML实例中存取target_txt而不是在XMLContentLoader实例中.幸好我们还有不少方法可以解决这个问题.

方法一,使用本地的一个变量.如果你使用类创建事件控制函数(onLoad),那么这个函数就已经向那个方法中所有的已经定义的本地变量声明了.如果你分配了需要的属性注释给一个主方法中的变量,它会在返回无效的范围执行.

var txt = target_txt; 
_xml.onLoad = function(success){ 
if (success) txt.text = this.firstChild.toString(); 
}

只能用于变量,对呼叫类的方法来说并不安全
方法二
在收到处理机的对象内定义变量.因为在onLoad内_xml实例在寻找自己的target_txt,而不是类实例的.你要做的就是复制这个变量,到_xml内,保持名字一样.然后,onLoad可以正确的处理这个变量了,现在,相反的一面就是,至少在XML对象中,你所使用的是非动态类了.那就是说你不能在技术上添加或读取没有在类中定义过的属性或方法了.不过你可以通过欺骗FLash的编译器通过相关数组的语法来定义你的属性.在这里就是target_txt.

_xml["target_txt"] = target_txt; 
_xml.onLoad = function(success){ 
if (success) { 
target_txt.text = this.firstChild.toString(); 

}
使用_xml["target_txt"]可以欺骗编译器,就象使用[]来存取变量.编译器并不能确定在[]中的是什么值(有意义或无意义的变量).所以,你就可以欺骗编译器了.在onLoad的时候,target_txt是可以被准确发现的,因为它被_xml定义了.更羞辱的是,便宜器并不能识别范围的变化(事实上,正在执行的ActionScript是知道的,只是编译器没生成在swf中.)除非你不想使用[]在onLoad函数中存取target_txt只能用于变量,对呼叫类的方法来说并不安全


方法三,在收到处理机的对象内定义一个类实例.这比较接近于前面的,只是加了一个类实例的解释而不是一个属性了.这在你处理比较多的变量或者需要使用在处理函数的范围你使用实例等情况比较需要.然后,再一次的,编译器在处理非动态的XML实例时,这增加了复杂性.当使用时你并不是复制一个已经存在的属性,所以编译器会认为它不存在.还好,编译器并不知道范围,这是为什么这个没被函数定义的属性可以被忽略.所以在处理onLoad时,如果一个类声明的变量是声明一个事实上属于一个被定义的处理机的对象的.它可以不被编译器理会(当然,可能和一些行为想矛盾),在XML实例初始化的类仍然需要[]来避过编译器.然而
_xml["hostInstance"] = this; 
_xml.onLoad = function(success){ 
if (success){ 
this.hostInstance.target_txt.text = this.firstChild.toString(); 

}
注:你也可以通过在类中创建一个没有定义的对象属性,这里叫hostInstance来避免是用[].如果你对你的代码有信心,你同样可以自己写XML实例来避免上面所说的关于编译器的问题. 
private var _xml;
综合三和一,使用一个本地变量来解释类实例.这是就不需要:
a)在事件处理器中的对象定义任何特殊的变量
b)欺骗编译器
c)为属性定义许多变量
var host = this; 
_xml.onLoad = function(success){ 
if (success){ 
host.target_txt.text = this.firstChild.toString(); 

}
方法四:使用Delegate Utility.在7.2版本里面已经有了.这可能是最官方的.同样是最模糊的一个方法.Delegate是2.0中mx.utils的一个类,使你可以改变呼叫函数的范围,比如从一个对象到另一个对象.基本上它是一个function.call()和function.apply()提供的功能包.Delegate只是方便了截取在另一个范围中执行的对象的函数.例子:
import mx.utils.Delegate; 
var objectA:Object = {name: "object A"}; 
var objectB:Object = {name: "object B"}; 
function getName():String {  
return this.name; 

objectB.getName = Delegate.create(objectA, getName); 
trace( objectB.getName() ); // traces "object A";
在这里,静态方法所创建的是用Delegate类来创建一个在对象B中被分配的函数(getName)但是,在运行的时候,在对象A的范围中使用.这意味着任何在那个函数中的实例都指向了对象A,而不是对象B了,即使是在对象B中被呼叫.这个可以在可以是用onLoad的Class的XML实例被提供.因此,使所有的类属性中的声明都无效,就象呼叫可以通过类定义实例的范围而不是XML对象.为了简单点,我们可以写一个函数来在类中使用onLoad方法.这无论如何都是最常见的

方法.使用Delegate.create()使分配更简单.这是个完整的类:
import mx.utils.Delegate; 
class XMLContentLoader { 
public var target_txt:TextField; 
private var _xml:XML; 
function XMLContentLoader(url:String, target:TextField){ 
target_txt = target; 
_xml = new XML(); 
_xml.ignoreWhite = true; 
_xml.onLoad = Delegate.create(this, onLoadEvent); 
_xml.load(url); 

function onLoadEvent(success:Boolean):Void { 
if (success) target_txt.text = _xml.firstChild.toString(); 

}
导入Delegate类以后,(使用import以后的mx.utils.Delegate,或者直接的mx.utils.Delegate.create())你可以在构造器中看到已经为_xml这个XML实例定义了onLoad事件.看到一个函数和一个对象,这个对象就是函数中所定义的对象.因为我们现在类的范围内使用onload,这把类表示成对象.这个函数是类随后自己定义的onLoadEvent函数.在运行的时候,会正确的把target_txt作为一个类的属性来处理.当然,你同样可以看到,因为这个onLoad方法的范围不是XML实例,而是代表了类._xml需要在读取XML实例时使用.
注:如果你使用类似前面的onLoadEvent的方法在类中定义自己的onLoad方法,那么使用本地变量的方法就是无效的了.
视频教程列表
文章教程搜索
 
Flash AS推荐教程
Flash AS热门教程
看全部视频教程
购买方式/价格
购买视频教程: 咨询客服
tel:15972130058