1

多年来,我一直在使用 Flex / Flash Builder。最新版本的 Flash Builder (4.7) 似乎有很多问题,其中最大的问题是:

  • 不检测IDMXML 中的组件。例如,您无法查找组件 ID 的用法。将光标保持在组件的 ID 上甚至不会标记ID 的出现。相反,它标记id了 MXML中实际单词的出现。
  • 极慢

我正在认真评估迁移到 IntelliJ IDEA 12,尤其是在阅读了许多经验丰富的 Flex 开发人员对它赞不绝口并推荐它之后。

我尝试过这个。我花了一段时间才熟悉 IDE 的新术语(这篇文档和 JetBrains 非常乐于助人的支持人员让我很容易理解)。

我能够使用 Adob​​e Flex 4.6 SDK 在 IDEA 中设置我的(大型)项目并让它编译得很好。但我注意到我的 AS 文件中突出显示的许多“错误”实际上都是误报。

ActionScript 编辑器似乎无法识别 MXML 中定义的对象。显然,这是 IDEA 中的一个已知错误(在此处跟踪)。而且这个bug已经存在2年多了!

引用 JetBrains 支持人员的话:

我必须承认,突出显示不包含类但包含在mxmlas<fx:Script source="some_file.as"/>中的 ActionScript 文件可能是 IntelliJ IDEA 代码突出显示的唯一薄弱部分。如果您在 CDATA 中嵌入 AS 代码<fx:Script/>而不是作为外部*.as文件引用,则错误的错误突出显示将消失。虽然我知道这并不总是需要的。

恐怕修复不会进入 12 版本,因为发布很快而且修复风险太大。问题的优先级取决于投票和用户反馈。到目前为止,我们只有 2 票 (http://youtrack.jetbrains.com/issue/IDEA-52598),由于修复非常复杂,我们仍然没有实施它,认为这是一个罕见的用例。我希望在 12.x 更新版本之一中修复它。

我的项目是一个巨大的项目,有巨大的 MXML 文件,每个 MXML 的 AS 代码甚至更多。因此,出于组织目的,我需要在逻辑上将它们拆分为较小的文件。因此,将 AS 代码与 MXML 合并是不切实际的。错误的错误突出显示会大大降低代码的可读性。此外,它不允许在 AS 代码中单击 Control / Command-click组件 ID 快速导航到 MXML 中的组件定义(顺便说一句,现在在 FB 4.7 中也被破坏了,但在 FB 4.6 中运行良好)。

不幸的是,IDEA 中的这个错误对我来说是一个交易破坏者。但我想知道其他 Flex 开发人员如何能够克服/解决这个看似严重的错误。

让我难以置信的是,只有 2 人受到了这个 bug 的影响,尤其是在有这么多 Flex 开发人员推荐 IDEA 的情况下。也许我做错了什么?

所有 Flex 开发人员,我将不胜感激您的想法。

更新

这是对 RIAStar 出色而详细的回答的回应。但这并不能完全帮助我。让我解释一下为什么以及如何使用<fx:Script source>. 我使用的是 Flex 4.x,几乎只有 Spark 组件。

  • 假设一个全新的 Flex 项目。主应用程序是一个 MXML 文件。
  • 在这个 MXML 文件中,假设我有一个注册表单。
  • 在编辑表单(在每个字段中)时,假设我必须运行验证并仅在表单完全有效时启用提交按钮。这意味着我需要将更改事件处理程序分配给表单项。事件处理程序是 AS 代码。
  • 假设有一个用户名字段需要通过异步调用服务器进行类型唯一性检查。服务器通信代码也是AS代码。
  • 当然,还有提交按钮处理程序,它也是 AS 代码。

我通常将所有 AS 代码放在单独的.as文件中,并使用<fx:Script source>. 这个 AS 代码通常很重,有很多功能和行为逻辑。很多时候,基于用户操作,甚至 MXML 中的组件和元素的布局都通过这个 AS 代码进行修改。

如果我理解你们的话,这些事件处理程序代码都不应该在这些 MXML 脚本文件中。那么,它应该在哪里呢?你们是怎么做到的?我不确定 Spark Skinning 架构与此有何关系。

4

2 回答 2

14

既然我想不出一个温和的说法,我就直言不讳:恐怕只有两个人认为这是一个严重的错误,因为大多数经验丰富的 Flex 开发人员会同意使用<fx:Script source="some_file.as"/>是不好的做法.
您有效地创建了代表一个类的两个文件。从您似乎担心的可读性 POV 来看,这不是一个好举措。其中一个文件(.as 文件)只是一堆无法单独存在的函数:它们与另一个文件/类紧密耦合,但仅查看 .as 文件无法知道哪个类它耦合到。当然,您可以使用某种命名约定来解决此问题,但最终 ActionScript/Flex 应该用作静态类型语言,而不是依赖于 mixins 和命名约定的脚本语言(不要误会我的意思:我并不是说脚本语言是不好的做法;这不是 ActionScript 的构思方式)。

那么你的替代方案是什么?
我想这种构造背后的主要原因是您希望将 MXML 与 ActionScript 代码分开,或者用更抽象的术语:将视图与逻辑分开。幸运的是,这可以通过其他一些更清洁的方式来实现。您可以使用哪些解决方案取决于我们谈论的是 Flex 3(或更早版本)还是 Flex 4。我意识到您可能没有时间将代码重构为建议的解决方案之一,但我不想离开您只是一个“这不是好的做法”的答案。

弹性 3 (mx)

代码隐藏:许多开发人员使用所谓的“代码隐藏”模式将他们的逻辑与他们的视图分开。您可以通过谷歌搜索“flex code behind”找到有关该主题的大量信息。我不需要在这里重复所有这些。我不太喜欢这个概念,因为它严重依赖于继承,并且两个生成的类仍然非常紧密耦合,但至少我们在谈论两个。如果你设计好你的架构,你甚至可以重用你的一些基类。

编写模型和控制器:我曾经为每个 MXML 视图创建一个单独的“表示模型”类和一个“控制器”类,然后像这样使用它:

<!--MyView.mxml-->
<mx:VBox>
    <m:MyModel id="model"/>
    <c:MyController model="{model}" view="{this}"/>
    ...
</mx:VBox>

MVC 纯粹主义者不会喜欢这样,但它在 Flex 应用程序的上下文中对我来说工作得很好。
后来当直接注入支持框架(如 Parsley)出现时,我可以使用注入来连接所有这些类,而不是像本例中那样硬连接它们。

MVC 框架:我对这个主题的了解很少(因为在我看来 Flex 是一个非常不错的 MVC 框架,不需要第三方添加,但这是另一个讨论),但简而言之:它们可以帮助您将逻辑与视图分离干净的方式。

Flex 4(火花)

在 Flex 4 中,引入了 Spark 皮肤架构,它允许很好地分离视图和逻辑。您在包含所有行为代码的普通 ActionScript 中创建了一个所谓的“宿主组件”类,并在 MXML 中创建了一个定义组件的可视化表示的“皮肤”类。这使得设计可重用组件变得非常容易。

根据您的要求,这里有一个简化示例,说明您可以如何使用 Spark 皮肤来创建您的注册表单。
让我们从皮肤类开始,因为它很容易理解。它只是一个带有一些输入字段的表单。元HostComponent数据告诉皮肤它应该与 SignUp 主机组件一起工作。

<!--SignUpSkin.mxml: the visual representation-->
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Metadata>
        [HostComponent("net.riastar.view.SignUp")]
    </fx:Metadata>

    <s:Form>
        <s:FormHeading label="Sign up"/>

        <s:FormItem label="User name">
            <s:TextInput id="userInput"/>
        </s:FormItem>

        <s:FormItem label="Password">
            <s:TextInput id="passwordInput" displayAsPassword="true"/>
        </s:FormItem>

        <s:Button id="submitButton" label="Submit" 
                  enabled="{hostComponent.canSave}"/>
    </s:Form>

</s:Skin>

现在是纯 ActionScript 中的宿主组件。它必须扩展SkinnableComponent才能使用我们的皮肤(还有SkinnableContainer我最近在这个问题中解释过的:Flex mxml custom component - how to add uicomponents?,但我们在这里不需要它)。

public class SignUp extends SkinnableComponent {

    [SkinPart(required="true")]
    public var userInput:SkinnableTextBase;

    [SkinPart(required="true")]
    public var passwordInput:SkinnableTextBase;

    [SkinPart(required="true")]
    public var submitButton:IEventDispatcher;


    [Bindable]
    public var canSave:Boolean;


    override protected function partAdded(partName:String, instance:Object):void {
        super.partAdded(partName, instance);

        switch (instance) {
            case userInput:
                userInput.addEventListener(TextOperationEvent.CHANGE, 
                                           handleUserInputChange);
                break;
            case passwordInput:
                passwordInput.addEventListener(TextOperationEvent.CHANGE, 
                                               handlePasswordInputChange);
                break;
            case submitButton:
                submitButton.addEventListener(MouseEvent.CLICK, 
                                              handleSubmitButtonClick);
        }
    }

    private function handleUserInputChange(event:TextOperationEvent):void {
        validateUsername(userInput.text);
    }

    ...

}

这里有什么重要的?
标记为的变量SkinPart将自动分配给您刚刚创建的皮肤中存在的具有相同 id 的组件。例如<s:TextInput id="userInput"/>将被注入public var userInput:SkinnableTextBase;. 注意类型不同:SkinnableTextBaseTextInput;的基类 这允许我们使用例如 aTextArea而不是 a创建另一个皮肤,TextInput并且它可以在不接触主机组件的情况下工作。
partAdded()每当将 SkinPart 添加到显示列表时都会调用它,这就是我们连接事件侦听器的地方。在此示例中,我们将在其值更改时验证用户名。
验证完成后,您可以简单地将canSave属性设置为truefalse. 绑定在皮肤上的这个属性会自动更新Button的enabled属性。

并一起使用这两个类:

<v:SignUp skinClass="net.riastar.skin.SignUpSkin"/>
于 2012-12-27T00:22:03.787 回答
0

我实际上已经非常喜欢使用 RobotLegs。

在我的 MXML 视图中,我尝试将所有逻辑保留在 MXML 之外,并简单地将事件分派给中介。从那里我可以将代码放入所需的更重的 AS 的调解器中。

于 2013-01-08T00:04:07.367 回答