2009-01-08 6 views
3

Flex 3 mxml 구성 요소가 있다고 가정 해 봅시다. A에는 get/set 특성 인 'b'가 있습니다. A에서 mxml을 사용하여 지정되는 다른 내부 구성 요소 C가 있습니다. mxml 내에서 구성 요소 A를 "인스턴스화"할 때 선언에서 b 값을 지정할 수 있으며 모든 것이 올바르게 작동합니다. 그러나 Actionscript를 사용하여 구성 요소를 초기화 할 때 먼저 해당 구성 요소의 특성 (이 경우 'b')을 설정하기 전에 렌더링 된 컨테이너에 해당 구성 요소를 추가해야합니다. 속성 'B'에 대한 세터가 어떻게 든플렉스 3 - AS3을 사용할 때 구성 요소를 설정하기 전에 구성 요소를 추가해야합니까?

그래서 A. 내 C에 액세스 할 때이 중 하나, 다른 한편으로는 (은 C가 null 말한다)이 런타임에 실패

var a:A = new A(); 
a.b = "woopy"; //Sets the Label (declared in mxml) withn A to "woopy" 
this.addChild(a); 

를 발생 다음의

<customNamespace:A b="woopy"/> 

또는 같이

var a:A = new A(); 
this.addChild(a); 
a.b = "woopy"; //Sets the Label (declared in mxml) withn A to "woopy" 

을 작동, 더 런타임 오류 메시지가 던져 없다 컨테이너에 구성 요소가 추가 된 후 특성이 설정되면 n. 좋아,이 의미가, 나는 구성 요소의 내부가 실제로 구성 요소가 컨테이너에 추가되기 전까지는 생성되지 않는다고 가정합니다. 아직도, 이것은 일종의 성가심입니다. 구성 요소 내부를 컨테이너에 추가하지 않고도 완전히 렌더링되도록 보장 할 수있는 방법이 있습니까? 나는 actionscript와 mxml을 사용할 때와 다른 느낌을 좋아하지 않습니다. 기본적으로 속성 "인수"가없는 mxml에서 A를 선언하는 것은 AS에서 new 연산자를 사용하여 A를 선언하는 것과 같습니다. 최소한 A. 내부 상태에 관해서.

답변

8

강제로 자식 컨트롤을 만들려면 initialize 메서드를 호출해야합니다.

이 작동합니다 즉 :

var a:A = new A(); 
a.initialize(); 
a.b = "woopy"; 
this.addChild(a); 

을하지만, 스크립트 블록에서 선언 된 공용 변수에 대한 내부 통제 구속력 MXML 컨트롤을 선언 할 때 내가 지금까지 뭘했는지. 예 :

<?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> 

이렇게하면 컨트롤이 생성되었는지 여부에 대해 걱정할 필요없이 매개 변수를 설정할 수 있습니다.

4

맞아요. B의 세터가 C에서 작동하면 문제가 생길 수 있습니다. 왜냐하면 A가 생성 될 때 C가 A의 MXML에서 C를 선언 했더라도 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 사이트에서 an excellent video이라는 사이트를 세부적인 단계별로 게시했습니다. 나는 그녀가 그것을 녹음 한 MAX에서 연설에 참석했는데, 그것은 회의의 최고 중 하나였습니다. 그 디테일과 포괄 성을보고 지켜보고 다시 본다. 그녀는 실제로 이야기하는 동안 여러 번 질문에 답합니다. 좋은 물건이야.

행운을 빈다.

2

기본 질문에 대답하려면 해당 속성을 설정하려면 표시 목록에 AS3으로 인스턴스화 된 구성 요소를 추가 할 필요가 없습니다. 물론 MXML에서 생성하는 것과 AS3에서 생성하는 것 사이에는 차이가 없습니다 ... 물론 구성 요소가 제대로 구축되지 않은 경우는 예외입니다.

Adobe (이전 Macromedia)의 Flex 팀은 Flex 구성 요소 아키텍처에 대한 수년간의 최적화 최적화 작업을 수행했습니다. 문제에 관련되는 디자인의 두 가지 중요한 부분이 있습니다

당신이 한 번에 여러 속성을 설정할 수 있지만, 변화의 효과까지 발생하지 않도록 그들은 무효화 및 검증의 시스템을 설계
  1. 모든 변경을 완료했습니다.

  2. 구성 요소를 처음 인스턴스화하면 해당 구성 요소가 즉시 만들어지지 않습니다. 이를 수행 할 최적의 시간이 있습니다. 컴포넌트가 디스플레이 목록에 추가 된 후입니다. 당신이 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 구성 요소를 구축 할 경우

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>