2009-02-02 3 views
1

Я создаю приложение, в котором у меня есть два компонента mxml, MainPanel.mxml и TextPanel.mxml, которые содержатся в родительском приложении с именем index.mxml. Когда я ввожу что-то текстовое поле, существующее в TextPanel.mxml, я хочу привязывать эти данные к метке, которая существует в TextPanel.mxml. Я знаю, что это может быть достигнуто, выполнив следующие действия:слабо связанные компоненты Flex 3 sibling

<mx:Label text="{Application.application.textArea.text1.text}" /> 

Однако я хочу сделать свой компонент более легко заменяемый с системой, и это создает зависимости, которые я не хочу.

Следующее - это решение, с которым я придумал, хотя я чувствую, что есть лучший способ там (какой-то код опущен для краткости).

index.mxml (родительское приложение):

<mx:Script> 
    <![CDATA[ 

     [Bindable] 
     private var _text:String; 

     private function handleTextChange(input:String):void { 
      _text = input; 
     } 

    ]]> 
</mx:Script> 

<tp:TextPanel id="textArea" 
    textChange="handleTextChange(event.stringData)"/> 

<cp:MainPanel id="mainArea" text = "{_text}" /> 

TextPanel.mxml:

<mx:Metadata> 
    [Event(name="textChange", type="events.CustomStringDataEvent")] 
</mx:Metadata> 

<mx:Script> 
    <![CDATA[ 
     import events.CustomStringDataEvent; 
     private function textChangeHandler(event:Event):void { 
      var input:String = event.target.text; 
      dispatchEvent(new CustomStringDataEvent(input, 'textChange')); 
     } 
    ]]> 
</mx:Script> 
<mx:TextInput id="text1" change="textChangeHandler(event)"/> 

MainPanel.mxml

<mx:Script> 
    <![CDATA[ 

     [Bindable] 
     public var text:String; 

    ]]> 
</mx:Script> 
<mx:Label text="{text}" /> 

Итак, наконец, на мой вопрос, , что является лучше всего создать свободную связь между двумя родственными компонентами?

ответ

2

Это один из способов сделать это, конечно. Но вы также можете создать другой класс, например, для хранения данных, написанных одним (или любым) из ваших компонентов, а затем дать каждому компоненту ссылку на этот объект; что может привести к такому же эффекту с меньшим количеством обработки кода и ручного управления событиями.

Например, класс объект, содержащий данные может выглядеть следующим образом (обратите внимание на атрибут Bindable на общественном члене:

package 
{ 
    public class MyBindableObject 
    { 
     [Bindable] 
     public var myStringProperty:String = "";   

     public function MyBindableObject() 
     { 
      // 
     } 
    } 
} 

... и основное приложение контейнер, который бы создать экземпляр объекта первоначально (и раздайте ссылки на его подкомпоненты), например:

<?xml version="1.0" encoding="utf-8"?> 
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:local="*" initialize="this_initialize(event)"> 

    <mx:Script> 
     <![CDATA[ 

      [Bindable] 
      private var myObject:MyBindableObject; 

      private function this_initialize(event:Event):void 
      { 
       myObject = new MyBindableObject(); 
      } 

     ]]> 
    </mx:Script> 

    <mx:TextInput text="{myObject.myStringProperty}" /> 
    <local:MyCustomComponent myObject="{myObject}" /> 
    <local:MyOtherCustomComponent myObject="{myObject}" /> 

</mx:WindowedApplication> 

...и MyCustomComponent (обратите внимание на Bindable & Inspectable атрибуты), которые в данном случае случается писать myObject.myStringProperty непосредственно:

<?xml version="1.0" encoding="utf-8"?> 
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"> 

    <mx:Script> 
     <![CDATA[ 

      [Bindable] 
      [Inspectable] 
      public var myObject:MyBindableObject; 

      private function myEventHandler(event:Event):void 
      { 
       myObject.myStringProperty = txt.text; 
      } 

     ]]> 
    </mx:Script> 

    <mx:TextInput id="txt" text="{myObject.myStringProperty}" keyUp="myEventHandler(event)" /> 

... и MyOtherCustomComponent, который принимает изменения, сделанные в предыдущем компоненте (и которые, кстати распространяются на приложение контейнера, а):

<?xml version="1.0" encoding="utf-8"?> 
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"> 

    <mx:Script> 
     <![CDATA[ 

      [Bindable] 
      [Inspectable] 
      public var myObject:MyBindableObject; 

     ]]> 
    </mx:Script> 

    <mx:TextInput text="{myObject.myStringProperty}" /> 

</mx:Canvas> 

так снова, приложение контейнер инициализирует экземпляр объекта, связывает один из своих свойств своих подкомпонентов со значением свойства этого объекта (необязательно) и ссылки на этот объект ссылаются на какой-либо из его подкомпонентов, возможно, захочет его использовать. Второй компонент в этом случае записывает значение, а два других немедленно получают изменения, так как myStringProperty в классе MyBindableObject помечен как Bindable, и каждый компонент содержит прослушиватель для изменения этого свойства.

Пример несколько прост в том, что он действительно просто устанавливает строковое значение для какого-либо объекта, тем самым выгружая работу диспетчеризации событий в фреймворк Flex, что устраняет только несколько строк кода - но это, вероятно, хорошая вещь здесь, поскольку нет необходимости создавать настраиваемое событие для простых событий изменения текста/изменения свойств, поскольку Flex обрабатывает много или даже всю эту работу для вас.

Тем не менее, это зависит от того, насколько вы хотите настроить свой TextPanel. Если бы вы хотели развить его в более сложный компонент, то я бы предположил, что вам нужно перенести экземпляр исходного объекта в сам TextPanel, сделайте так, как вы это делали, определяя и отправляя дополнительные пользовательские события и имея основное приложение и компонент для родного брата прослушивать уведомления о событиях для компонента или связанного объекта, либо с помощью textPanel.addEventListener (или аналогично встроенного в MXML), либо textPanel.myObject.addEventListener, в зависимости от того, какие из них были подходящими.

+0

Я не понимаю, почему вы сделали собственность. В этом нет необходимости. – sharvey

1

Что вы сделали здесь, это своего рода реализация mediator pattern, что является совершенно приемлемым способом выполнения действий и, вероятно, «лучшей практикой», которую вы ищете, на мой взгляд, поскольку компоненты вы используете, не зависят напрямую друг от друга - они просто отправляют события и позволяют кому-то другому выполнять функции «более высокого уровня».

Альтернативный способ сделать это: dependency injection, где вы даете ссылки на компоненты друг другу и позволяете им общаться напрямую. Таким образом, вы бы сделать компоненты зависимыми друг от друга (или, может быть, не совсем друг другу, но все, что реализует одни и те же интерфейсы), но вам не нужно будет писать какой-либо код посредника. Здесь, в отличие от шаблона медиатора, функциональность «более высокого уровня», на которую я ссылался, на самом деле была бы ответственностью самих компонентов, а не кого-то другого (посредника.)

Смежные вопросы