слабосвязанные компоненты Flex 3 - PullRequest
1 голос
/ 02 февраля 2009

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

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

2 голосов
/ 02 февраля 2009

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

Например, объект класса, содержащий данные, может выглядеть примерно так (обратите внимание на атрибут 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, сделать то, что вы сделали, определив и отправив дополнительные пользовательские события, и имея основной компонент app и родственный компонент прослушивать уведомления о событиях в компоненте или в привязываемом объекте, либо с помощью textPanel.addEventListener (или аналогично встроенному в MXML), либо с помощью textPanel.myObject.addEventListener, в зависимости от того, какие из них являются подходящими.

1 голос
/ 02 февраля 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...