14

我在 ExtJS 4 中遇到了 MVC 模式的问题。至少,我认为我遇到了。在与多个人接触过这个问题,并在 Sencha 论坛上多次发帖后,我现在转向更广泛的受众,希望得到一个灯泡或确认。

问题

您的应用程序能够打开许多不同的视图,其中一些本身就是迷你应用程序。此外,用户可能希望打开一个视图的多个并发副本。

此应用程序是一个单页客户端 Javascript 应用程序。

ExtJS 4 MVC 模型希望您在 Application 类中定义所有控制器。然后在应用程序加载时初始化这些控制器。控制器跟踪视图、模型和存储。

当您多次初始化控制器 A 时,例如创建多个视图副本,您最终会得到两个引用相同数据存储的视图,并在功能上将重复事件发送到应用程序事件总线。

我通过向 Component 和 Controller 添加新的原型方法来重构我的应用程序,以允许 a) 子控制器(我的一些控制器变得非常庞大)和 b) 专门为它们使用的视图定义存储。模型仍然可以在控制器上定义,只是为了便于处理程序在您需要执行诸如从服务器获取记录之类的操作时使用。

问题

我对 MVC 的理解让我相信模型与 View 的关系比 Controller 更直接。我假设 ExtJS 4 决定将存储(我认为可以被视为更经典模型的包装器)附加到控制器,以鼓励重用加载的数据,并优化同一个类的多个副本实例化. 但是,在我看来,如果打算让用户使用多个视图实例,则无法做到这一点。在我看来,拥有多个实例是 OO 框架中的一个重要选项,因此我逆势而上并在一些 Ext 基类上实现了原型。(谢谢Ext.implement!)。

有没有办法使用开箱即用的 MVC 类并使用提供的 setter、getter 等来让视图的多个并发实例加载不同的数据?

4

7 回答 7

8

我遇到了类似的问题:

考虑一个 CRM 类型应用程序的选项卡面板,它为每个客户打开一个视图的新实例。并假设选项卡视图包含 3 或 4 个行编辑网格面板,用于与与该客户端相关的不同数据集合进行交互。

我想出的解决方案是基于 Sencha 论坛上的这个。简而言之,几乎所有从视图调度的事件都包含对视图本身的引用。我的控制器控制函数中的处理程序都使用这些来获取对正确视图实例的引用。

为了处理为此所需的同一商店的多个实例,我从该帖子中牢记这一点:

对于视图上的 Store 实例或全局实例...取决于需要。如果要全局使用,则将其设为全局。如果您只需要在视图上使用它,则将其放在视图上。MVC 不是法律,您可以根据需要对其进行更改。从技术上讲,MVC 的控制器部分被认为是视图和模型部分之间的中间人,但有时这并不是必需的。我有 95% 的时间在视图中创建商店。我给你举个例子...

如果您有一个产品商店,您可能只需要在您的网格中引用该商店。应用程序的其他部分通常不需要这样做。但是,如果您有一个 Store 来加载国家/地区,我经常需要在全球范围内使用它,因此我只需加载一次,然后可以在多个视图中设置/使用该 Store。

所以我只是在视图的 initComponent 方法中创建了与视图实例相关的所需存储。该应用程序确实有一些我按照 MVC 建议创建为存储类的全局存储。将视图实例存储封装在视图中效果很好。然后我只需要一个控制器实例。

为了具体回答您的问题,目前没有 ExtJS 官方建议或配置来处理使用相同存储构造函数的同一视图的多个实例。我花了一些时间寻找类似的东西,我发现最好的是他们的一位论坛版主的推荐。

于 2012-05-02T15:36:13.273 回答
2

我认为无论您拥有多少视图/模型,您都不需要超过 1 个控制器实例。请参阅此处的功能示例:

http://whatisextjs.com/extjs-4-extension/fieldset-w-dynamic-controls-7

于 2011-12-05T15:32:22.860 回答
2

这可以相当容易地完成。你需要遵守一些规则:

  1. 在应用程序启动时加载您的控制器。不要卸载它们。不用担心内存或时间,即使对于数百个控制器来说,它也很小,只要你最小化和连接你的 js。

  2. 永远不要使用控制器的 refs 或 views 属性。您将使用一个控制器实例,但使用多个视图实例,因此您永远不需要对视图的引用。

  3. 仅在控制器中使用事件侦听器。你只会在你的观点上听事件。您始终可以通过处理程序中的“cmp”参数获得对事件处理程序中视图的(临时)引用。

  4. 要“启动”视图,请创建它并将其添加到另一个视图。要摧毁它,摧毁它。您不使用控制器来启动视图。您可以使用控制器中的 afterrender 和 beforedestroy 事件来添加逻辑。

于 2012-11-04T22:07:18.037 回答
1

在 ExtJS 的 MVC 中,控制器是一个单例供您查看。我喜欢DeftJS对 MVC 的看法。视图的每个实例都有自己的控制器实例。通过这种方式,您可以将所有“控制规则”放在视图特定部分的控制器中,并且仅在视图打开时才会实例化。

我没有任何经验如何在同一个项目中使用多个 Defts JS 应用程序。

于 2012-11-14T10:48:25.713 回答
0

你如何创造你的观点?我看不出为什么您不能将不同的存储或配置数据传递给每个对象。一些代码示例将有助于您确切地在做什么。例如,我们有一个类似的声音应用程序,一切都是通过扩展完成的。所以,如果我们需要一个网格,我们运行

Ext.define('MyApp.grids.something',{
extends:'Ext.grid.panel' 
//...

这些类是预定义的。然后,当控制器或视图加载此网格时,它们正在使用

var grid=Ext.create('MyApp.grids.something',{id:'unique',store:mystore});

如您所见,我们可以在每次创建同一个网格时将不同的配置选项传递给它。我们可以像对待您一样对待它

Ext.create('Ext.grid.Panel');

当然,除了我们预先定义了一些选项,以及一些不可覆盖的选项,等等。

希望这有帮助。

于 2011-12-06T20:01:26.487 回答
0

当然。是什么让你不相信?下面是创建从 Window 组件扩展的自定义 View 的示例。你可以从同一个控制器多次运行这个方法,每次你都会得到一个新的视图实例。

“this”是指代码在其中运行的控制器:

       this.getRequestModel().load(requestID,{       //load from server (async)
                 success: function(record, operation) {
                        var view = Ext.widget('requestEdit',{
                            title: 'MyRequest '+requestID
                        });
                        var form = view.down('form');
                        form.loadRecord(record);
                 }
         });
于 2011-12-01T08:08:03.790 回答
0

看看这篇文章。想法是从视图配置中获取一些配置(如storeitemId)并将其放入视口配置中:

// .../app/view/Viewport.js
Ext.define('MyApp.view.Viewport', {
    // ...
    items: [
        // ...
        { xtype: 'testview', store: 'Store1', itemId: 'instance1' },
        { xtype: 'testview', store: 'Store2', itemId: 'instance2' }
    ]
});

显然,商店的问题将得到解决。不同itemId的 s 将使您能够正确处理事件。

于 2013-03-20T20:26:31.947 回答