在 Ext JS 4 MVC 应用中,什么应该负责加载商店

In an Ext JS 4 MVC app, what should be responsible for loading stores?

本文关键字:加载 什么 JS Ext MVC 应用      更新时间:2023-09-26

考虑一个复杂的应用程序,其中您具有自定义过滤逻辑和不同的加载模式;隐藏时延迟加载,隐藏时不加载,但在显示时加载,修改自定义过滤器时重新加载等。

MVC 应用程序的哪个部分应该负责加载,以及如何连接它们?

当我开始使用 MVC 时,我从未从 Sencha 找到明确的答案,但我可以告诉你我成功地为一些应用程序做了什么。

我根据商店的使用方式创建和加载商店。这对我来说似乎分为三个不同的类别:

  1. 适用于整个应用的应用商店

  2. 应用于视图的所有实例的存储

  3. 绑定到单个视图实例的存储

1. 适用于整个应用程序的商店

我通常有一个"主"控制器来处理我的应用程序的框架,如键盘导航、主菜单等。

属于上述第一类的商店将进入此"主"控制器的stores数组。如果这些商店不依赖于另一家商店,那么我只需将它们autoLoad: true并完成它们。但是,如果它们依赖于另一个存储数据,则我向父存储添加一个侦听器,以将依赖存储加载到父存储的onLoad事件中。

发现属于第一类的一些商店的一个例子是我在整个应用程序的组合框中使用的参考商店,通常在许多不同类型的视图中。这些通常配置了autoLoad: true,然后我再也不会为该用户的会话加载它们。每当我需要使用引用存储的组合框时,我都可以像这样设置它:

{
    xtype: 'combobox',
    allowBlank: false,
    forceSelection: true,
    store: Ext.getStore('SomeReferenceStore'),
    queryMode: 'local', // this makes sure the store doesn't reload
    valueField: 'id',
    displayField: 'name'
}

举一个两个商店的例子,它们都属于第一类,其中一个依赖于另一个:

在我的一个应用程序中,我有一个动态数量的用户权限,当用户登录到应用程序时,我需要获取不同的权限并修改User模型以包含这些不同权限中的每一个的布尔字段:

Ext.define('MyApp.controller.Main', {
    extend: 'Ext.app.Controller',
    models: [
        'User', 
        'Reference',
        // etc...
    ],
    stores: [
        'CurrentUser', 
        'PermissionRef', // this is "autoLoad: true"
        // etc...
    ],
    init: function() {
        var me = this;       
        // update the user model and load the user
        me.getPermissionRefStore().on('load', function(store, records) {
            var model = me.getUserModel(),
                fields = model.prototype.fields.getRange();
            // append the permissions onto the User model fields
            Ext.each(records, function(permission) {
                fields.push({
                    name: permission.get('name'), 
                    type: 'bool',
                });
            });
            // update the user model with the permission fields
            model.setFields(fields);
            // load the current user
            me.getCurrentUserStore().load();
            // other stuff...
        });
        // other stuff...
    }
});

有了这个,每当我需要对用户的引用以及他拥有哪些可用权限时,我只需调用:

var user = Ext.getStore('CurrentUser').first();

有时,视图还取决于正在加载的存储。例如,我的主菜单项由数据库表确定,在这种情况下,我将以相同的方式包含一个onLoad侦听器(在控制器的init函数中(:

// create the menu once we know what menu items are available
me.getMenuStore().on('load', function(store) {
    me.getViewport().add(Ext.widget('mainpanel'));            
});

MyApp.store.Menu本身将配置autoLoad: true .

2. 适用于视图所有实例的存储

我创建和加载这些就像第一个类别一样,只是将它们放在特定视图控制器的stores数组中,而不是"主"控制器stores数组中。

然后是相同的基本概念,如果它们依赖于其他商店的数据,则有些是autoLoad: true有些则不是。

对于不autoLoad: true的,它们被加载到控制器init函数内的某个地方,或者由于某些事件被触发

3. 绑定到单个视图实例的存储

在这里,我可能会违背 MVC 的理念,但对于适用于视图的单个实例而不是视图本身的商店来说,确实没有比这更好的地方了。

在大多数情况下,我甚至不会将这些存储放在视图控制器的stores数组中。我只是在视图的initComponent函数中创建并加载它们。因此,当视图被销毁时,不再引用存储,因此存储也会被销毁。这有助于减少可以多次创建的商店的资源。

例如,假设您有一个扩展gridpanel并显示独角兽随时间推移的渐进权重的MyApp.view.UnicornWeightGrid。用户可以打开领域内所有独角兽的UnicornWeightGrid,以便进行比较和交叉引用。UnicornWeightStore的不同实例与UnicornWeightGrid实例一样多。

视图可以定义如下:

Ext.define('MyApp.view.UnicornWeightGrid', {
    extend: 'Ext.grid.Panel',
    alias: 'widget.unicornweight',
    requires: [
        'MyApp.model.UnicornWeight'
    ],
    closable: true,    
    initComponent: function() {
        var me = this;
        me.store = Ext.create('Ext.data.Store', {
            model: 'MyApp.model.UnicornWeight',
            proxy: {
                type: 'ajax',
                url: 'unicorns/weight',
                extraParams: {
                    name: me.unicornName
                }
            }
        });
        me.store.load();
    });
});

然后,每当我们想获得不同的UnicornWeightGrid我们可以简单地调用:

var grid = Ext.widget('unicornweight', {
    unicornName: someUnicornNameVariable
});
myTabPanel.add(grid);

在视图中定义的存储上我需要的任何onLoad侦听器,我也会附加到视图中。所以我真的不需要其他任何地方的参考。

综上所述,这绝不是建立商店的唯一方法。

我发现这是在创建几个不同的 ExtJS "MVC" 应用程序时始终如一地处理商店的最可行方法,但我有时在"特殊"情况下也会以不同的方式做。

你应该记住,"MVC"是一个非常松散的设计模式,它在我使用的几乎每个框架中的定义和实现都不同。因此,您几乎可以做最适合您的事情。

您应该将逻辑加载到网格的控制器中,该网格将显示此存储。我把它们放在afterrender事件的处理程序中。