【问题标题】:Passing data between views and models in Flex MVC framework在 Flex MVC 框架中的视图和模型之间传递数据
【发布时间】:2012-07-07 10:46:37
【问题描述】:

我以前从未使用过 Flex/Actionscript,所以如果我问任何明显的问题,请原谅我,但在写这篇文章之前,我已经为此工作了 3 天(包括搜索 google 和 stackoverflow)。

有人要求我修改一个用基于 mini-IoC 的 MVC 框架制作的用 Flex 4 编写的游戏。我被要求制作的两个模组是一个游戏结束屏幕,它在介绍屏幕上显示最终得分和难度选择。我已经制作了游戏结束屏幕,并成功地设法让控制器在游戏计时器用完时将其调出。

所以现在,游戏结构如下:

Intro View -> Game View -> Game Over View

    ^                            |
    |__________ (retry?) ________|

第一个问题是将分数从 mainGame ActionScript 文件传递​​到游戏结束屏幕。

我尝试过的事情:

  • 在gameOverViewBase 中导入mainGame 并在gameOverView mxml 文件中调用mainGame.score 变量。

-编辑!!! = 如果我将 mainGame 中的 score 变量更改为常量,则上述方法有效,但如果它仍然是变量,控制器将不会加载 gameOverView 并且游戏位于空的 mainGame 视图中。

  • 每当玩家在游戏中得分时,创建一个函数,在 gameOverViewBase 中添加一个新的得分变量。
  • 在 MainGame 结束时将分数作为参数传递给 GameOverView

controller.loadGameOver(score);

这似乎是最合乎逻辑的方式。因此,我通过游戏的其他组件设置了 loadGameOver 以将整数作为参数来跟踪该函数,直到我到达主游戏动作脚本文件:

public function loadGameOver(score:int) : void
    {
        loadView(GameOverView);
    }

loadView 函数(如下所示)是我卡住的地方,因为我看不到在哪里传递 'score' 参数。它看起来像这样:

private function loadView(viewClass:Class, modelClass:Class = null) : void
    {

        var view:View = new viewClass();
        if(!view) throw new Error("Could not load view");

        viewContainer.removeAllElements();
        viewContainer.addElement(view);         

        view.controller = this;

    }

第二个问题是介绍界面的难度选择。我在 mxml 文件和 ActionScript 中的每个按钮上使用了 3 个按钮(简单、普通、硬):

protected function onEasyButtonClick() : void
    {
        set = "easy"
        controller.loadMainGame(set);
    }

再一次,我结束了上面的 loadView 函数。

总结一下:我需要知道如何在视图和模型之间传递数据。如果这不是理想的方法,我愿意接受您认为更好的任何其他方法。

谢谢!

附:我可以将我的源代码发送给任何愿意提供帮助的人:)

【问题讨论】:

    标签: apache-flex model-view-controller actionscript mxml


    【解决方案1】:

    您没有指定使用哪个 MVC 框架会有所帮助。但是,分数绝对应该是模型的属性,并且模型数据应该可以直接访问视图,可能通过绑定(感谢 weltraumpirat),或者通过一些中间类。

    我建议您查看一些现有的视图类,并尝试弄清楚它们是如何获取模型数据的。您可以使用这种方法来获取视图所需的数据。

    [编辑]:

    mainGame 属性未在您的 GameOverView 实例上设置,因此您无法通过绑定或跟踪访问其 score 属性。控制器类的loadView 方法接受Model 类引用,它用于构造新的Model 实例以供新的View 使用。不幸的是,这对您没有用,因为您的 GameOverView 需要为 MainGameView 创建的 MainGame 实例(其中包含当前分数)。

    我不知道以下内容是否符合您使用的框架的理念。但是,我会更改 loadView 方法以接受 Model 的实例而不是类引用,并在实例化控制器时创建并缓存对 MainGame 实例的引用。这样,您可以在创建 MainGameViewGameOverView 时将相同的 Model 引用传递给它们。

        public class WhackAMoleBase extends Application implements IGameController
        {
            public var viewContainer:Group;
            private var mainGame:MainGame
    
            public function WhackAMoleBase() : void
            {
                super();
    
                // Create and cache an instance of the main game Model
                mainGame = new MainGame();
    
                addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
            }
    
            public function loadIntroduction() : void
            {
                loadView(IntroductionView);
            }
    
            public function loadMainGame() : void
            {
                loadView(MainGameView, mainGame);
            }
    
            public function loadGameOver() : void
            {
                // Use the same instance of MainGame which the MainGameView 
                // has been using as the Model for the GameOverView
                loadView(GameOverView, mainGame);
            }
    
            // Accept a Model instance rather than a class Reference
            private function loadView(viewClass:Class, model:Model = null) : void
            {
                //Create a new instance of the supplied view
                var view:View = new viewClass();
                if(!view) throw new Error("Could not load view");
    
                //Clear any previous views in the container and add
                viewContainer.removeAllElements();
                viewContainer.addElement(view);
    
                //Property based dependency injection 
                view.controller = this;
    
                //There may or may not be a model required for the
                //requested view; check and instantiate appropriately
                if(model)
                {               
                    //Give model reference to the controller
                    //and link the view up to the model
                    model.controller = this;
                    view.model = model;
                }
            }
    
            private function onCreationComplete(event:FlexEvent) : void
            {
                //When the application is first created, we want to show the introductory view 
                loadView(IntroductionView);
            }
    
        }
    

    【讨论】:

    • 在 Flex 中,您可能希望为此使用绑定。
    • 它是围绕一个基于 mini-IoC 的 MVC 框架示例构建的,如果有帮助吗? “模型的属性”是指公共变量吗? @weltraumpirat 我也在变量上使用了 [Bindable] 标签,但它不会显示整个分数标签Score: {mainGame.score}
    • 如果您尝试绑定属性,那么它需要是模型的公共变量,或者可以通过公共 getter 方法从模型访问。或者,一些框架/实现可能会选择将数据作为事件对象的一部分推出,当数据更改时,该事件对象会发送到感兴趣的视图。你说绑定不会显示整个乐谱标签是什么意思?
    • 好吧,如果我尝试直接访问 mxml 文件中的 score 变量,则会加载视图的其余部分,而忽略调用 mainGame 中的 score 的整个标签。当我尝试在 gameover base 的 actionscript 中定义一个变量时,如下所示:protected var mainGame:MainGame; [Bindable] public var score:int = mainGame.score; gameOverView 甚至无法加载,游戏在 mainGameView 中挂起。
    • 你能在你的 mxml 文件中追踪 mainGame.score 的值吗?使用第二种方法,您在运行时是否看到任何错误?
    猜你喜欢
    • 1970-01-01
    • 2015-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多