如何构建共享多个组件的多个Cairngorm MVC项目?

时间:2009-06-05 14:10:53

标签: flex actionscript-3 model-view-controller code-reuse cairngorm

我最近在Flex中完成了自定义报表UI的项目。现在,我的任务是创建一个新的应用程序,它本质上是原始UI的“精简”版本。它将仅包含原始应用程序中的一些选项。此外,它需要是一个单独的应用程序。

我不想复制我的代码,因此我计划将一堆类从原始应用程序移动到可由两个应用程序共享的新库。但是,我正在试图弄清楚如何在我的MVC环境中完成这项工作。

例如,我有一个Accordion组件,允许用户过滤多个项目。每个Accordion子节点都是具有两个列表的自定义组件的实例(一个用于可供选择的实体,另一个用于用户选择的实体)。每个子组件都具有绑定到Model的属性和调用Cairngorm Events的函数。

这是一个简化的例子:

FiltersAccordion.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Accordion xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:local="*">
    <mx:Script>
        <![CDATA[
            import model.ModelLocator;

            [Bindable]
            private var __model:ModelLocator = ModelLocator.getInstance();
        ]]>
    </mx:Script>

    <local:GenreFilter availableGenres="{__model.availableGenres}" 
         selectedGenres="{__model.selectedGenres}" />

    <local:ArtistFilter availableArtists="{__model.availableArtists}" 
         selectedArtists="{__model.selectedArtists}" />

    <local:LabelFilter availableLabels="{__model.availableLabels}" 
         selectedLabels="{__model.selectedLabels}" />
</mx:Accordion>


GenreFilter.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Script>
        <![CDATA[
            import control.events.AddGenresEvent;
            import control.events.RemoveGenresEvent;

            import model.ModelLocator;

            [Bindable]
            private var __model:ModelLocator = ModelLocator.getInstance();

            [Bindable]
            public var availableGenres:ArrayCollection;

            [Bindable]
            public var selectedGenres:ArrayCollection;

            private function addGenresButton_clickHandler():void
            {
                var event:AddGenresEvent = new AddGenresEvent();

                event.availableGenres = availableGenres;

                event.selectedGenres = selectedGenres;

                event.itemsToAdd = availableGenresList.selectedItems;

                event.dispatch();
            }

            protected function removeGenresButton_clickHandler():void
            {
                var event:RemoveGenresEvent = new RemoveGenresEvent();

                event.availableGenres = availableGenres;

                event.selectedGenres = selectedGenres;

                event.itemsToRemove = selectedGenresList.selectedItems;

                event.dispatch();
            }

        ]]>
    </mx:Script>

    <mx:List id="availableGenresList" dataProvider="{availableGenres}" />

    <mx:VBox>
         <mx:Button id="addButton" icon="{rightArrowIcon}" width="22" 
            height="22" click="addGenresButton_clickHandler();" />

         <mx:Button id="removeButton" icon="{leftArrowIcon}" width="22" 
             height="22" click="removeGenresButton_clickHandler();" />
     </mx:VBox>

     <mx:List id="selectedGenresList" dataProvider="{selectedGenres}" 
         width="100%" height="100%" allowMultipleSelection="true" />
</mx:HBox>

ArtistFilter.mxml LabelFilter.mxml GenreFilter.mxml 的设计基本相同,但用于特定事件。< / p>

那我该怎么做呢?将我的模型移动到共享库中没有意义。我基本上只想在库中创建View组件。我完全不在这里,不管是什么?

1 个答案:

答案 0 :(得分:2)

这是Cairngorm的一大缺陷 - 你的观点与你的模特有关。也就是说,通过使您想要重用的组件更通用和封装,您可以减轻许多痛苦。然后,扩展它们以将它们与应用程序的其余部分相关联。

所以,你的第一个组成部分变为:

<?xml version="1.0" encoding="utf-8"?>
<mx:Accordion xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:local="*">
    <mx:Script>
        <![CDATA[
            [Bindable]
            public var availableGenres:ArrayCollection;

            [Bindable]
            public var availableArtists:ArrayCollection;

            [Bindable]
            public var availableLabels:ArrayCollection;

            [Bindable]
            public var selectedGenres:ArrayCollection;

            [Bindable]
            public var selectedArtists:ArrayCollection;

            [Bindable]
            public var selectedLabels:ArrayCollection;
        ]]>
    </mx:Script>

    <local:GenreFilter availableGenres="{availableGenres}" 
         selectedGenres="{selectedGenres}" />

    <local:ArtistFilter availableArtists="{availableArtists}" 
         selectedArtists="{selectedArtists}" />

    <local:LabelFilter availableLabels="{availableLabels}" 
         selectedLabels="{selectedLabels}" />
</mx:Accordion>

然后,您在每个应用程序中执行此操作(但具有不同的模型/事件)。

<library:SpecialAccordion ... 
    availableGenres="{_model.availableGenres}"
    availableArtists="{_model.availableArtists}"
    ... etc ...
    >

    <mx:Script>
        <![CDATA[
            import model.ModelLocator;

            [Bindable]
            private var __model:ModelLocator = ModelLocator.getInstance();
        ]]>
    </mx:Script>

</library:SpecialAccordion>

这有意义吗?这是“视图”和“组件”之间的区别。组件可以重用,而视图则不能。组件是封装的,视图是特定于应用程序的。