Apache flex Flex 3-使用AS3时,我必须在设置组件属性之前添加组件吗?

Apache flex Flex 3-使用AS3时,我必须在设置组件属性之前添加组件吗?,apache-flex,flex3,mxml,components,Apache Flex,Flex3,Mxml,Components,假设我有一个Flex3MXML组件,称为a。a有一个get/set属性,称为“b”。在A中,我有另一个内部组件C,它是使用mxml指定的。在mxml中“实例化”组件A时,我可以在声明中指定b的值,一切正常。但是,当我使用Actionscript初始化组件时,我必须首先将组件添加到渲染容器中,然后才能设置所述组件的属性(在本例中为“b”)。当属性“b”的setter以某种方式访问A中的C时,就会发生这种情况 所以,这在运行时失败(它说C是空的) 另一方面,以下任一项都将起作用 <custom

假设我有一个Flex3MXML组件,称为a。a有一个get/set属性,称为“b”。在A中,我有另一个内部组件C,它是使用mxml指定的。在mxml中“实例化”组件A时,我可以在声明中指定b的值,一切正常。但是,当我使用Actionscript初始化组件时,我必须首先将组件添加到渲染容器中,然后才能设置所述组件的属性(在本例中为“b”)。当属性“b”的setter以某种方式访问A中的C时,就会发生这种情况

所以,这在运行时失败(它说C是空的)

另一方面,以下任一项都将起作用

<customNamespace:A b="woopy"/>

如图所示,在将组件添加到容器后设置属性时,不会引发运行时错误消息。好的,这是有意义的,我假设在将组件添加到容器之前,不会实际创建组件的内部构件。不过,这还是有点烦人。有没有办法保证组件内部在不添加到容器的情况下完全呈现?我不喜欢使用actionscript与mxml时感觉的不同。我需要一个解决方案,这样在mxml中声明一个基本上没有属性“arguments”的a就相当于在AS中使用新操作符声明一个。至少,就A.

的内部状态而言,要强制控件创建其子控件,必须调用initialize方法

i、 e.这应该有效:

var a:A = new A();
a.initialize();
a.b = "woopy";
this.addChild(a);
然而,到目前为止,我在声明mxml控件时所做的是将内部控件绑定到脚本块中声明的公共变量。e、 g

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Script>
        <![CDATA[
            [Bindable]
            public var labelText:String = "[Default]";
        ]]>
    </mx:Script>
    <mx:Label text="{labelText}"/>
</mx:Canvas>

通过这种方式,您可以设置参数,而不必担心控件是否已创建。

没错——如果B的setter作用于C,您将遇到问题,因为在构造A时,C肯定还不存在,即使您在A的MXML中声明了C

关于是否有任何方法可以保证组件及其子组件在不将其添加到容器中的情况下完全呈现和可用,答案是否定的——框架不会在组件上执行其创建和呈现魔术,除非以某种方式通过MXML或addChild()将其添加到显示列表中

当然,您可以使用visible或includeInLayout属性(例如,在A组件上设置为false)来实际显示组件,或者如果必须在脚本中进行实例化,则可以侦听A的initialize或creationComplete事件(这两个都表明A的子对象已经创建并准备好对其执行操作),只需等待设置B,直到收到该通知。但一般来说,我不建议直接调用initialize()方法;它是一个框架方法,在addChild()之后自动调用总之,总的来说,让框架做它自己的事情比围绕它工作要好

var a:A = new A();
a.addEventListener(FlexEvent.INITIALIZE, a_initialize);
addChild(a);

private function a_initialize(event:FlexEvent):void
{
    a.b = "woopy";
    // ... and so on
}
所以,如果你想确定的话

Flex团队的工程师Deepa Subramaniam最近在她的网站上发布了详细的Flex组件模型;我参加了MAX的演讲,她在那里录制了它,这很容易成为会议中最好的演讲之一。值得一看(再看,然后再看)因为它的细节和全面性。她实际上在演讲中多次回答你的问题。这是很棒的东西


祝您好运!

要回答您的主要问题,不,如果您想设置AS3实例化组件的属性,您不必将其添加到显示列表中。在MXML中创建它与在AS3中创建它没有区别……当然,除非组件没有正确构建

Adobe(前身为Macromedia)的Flex团队花了多年时间优化Flex组件体系结构。该设计中有两个重要部分与您的问题有关:

  • 他们设计了失效和验证系统,以便您可以一次设置多个属性,但在完成所有更改之前,更改的效果不会发生

  • 当一个组件第一次被实例化时,它的子组件不会立即被创建。有一个最佳的时间来做这件事,那是在组件被添加到显示列表之后

  • 基本上,当您在MXML实例化组件和AS3实例化组件之间存在行为差异时,这是因为构建组件时没有考虑这两个特性

    行为不正常的组件可能会执行以下操作:

    private var label:Label;
    
    public function get b():String
    {
        return this.label.text;
    }
    
    public function set b(value:String):void
    {
        this.label.text = value;
    }
    
    问题是组件开发人员没有考虑到标签子组件可能尚未创建!最佳做法是将值保存在变量中并使其无效,以便稍后将其传递给子组件(验证周期直到组件初始化并创建子组件后才会发生)

    或者,如果构建MXML组件,可以执行类似的操作,但使用绑定而不是验证系统通常更容易:

    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
        <mx:Label text="{this.b}"/>
        <mx:Script><![CDATA[
    
        private var _b:String;
    
        [Bindable]
        public function get b():String
        {
            return this._b;
        }
    
        public function set b(value:String):void
        {
            this._b = value;
        }
    
        ]]></mx:Script>
    </mx:Application>
    
    
    
    private var label:Label;
    
    public function get b():String
    {
        return this.label.text;
    }
    
    public function set b(value:String):void
    {
        this.label.text = value;
    }
    
    private var label:Label;
    
    private var _b:String;
    
    public function get b():String
    {
        return this._b;
    }
    
    public function set b(value:String):void
    {
        this._b = value;
        this.invalidateProperties();
    }
    
    override protected function commitProperties():void
    {
        super.commitProperties();
        this.label.text = this._b;
    }
    
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
        <mx:Label text="{this.b}"/>
        <mx:Script><![CDATA[
    
        private var _b:String;
    
        [Bindable]
        public function get b():String
        {
            return this._b;
        }
    
        public function set b(value:String):void
        {
            this._b = value;
        }
    
        ]]></mx:Script>
    </mx:Application>