Javascript 在ExtJS4MVC应用程序中,应该由什么负责加载商店?

Javascript 在ExtJS4MVC应用程序中,应该由什么负责加载商店?,javascript,model-view-controller,extjs4,extjs-mvc,Javascript,Model View Controller,Extjs4,Extjs Mvc,考虑一个复杂的应用程序,其中有定制的过滤逻辑和不同的加载模式;隐藏时延迟加载,隐藏时不加载,但显示时加载,修改自定义过滤器时重新加载等 mvc应用程序的哪个部分应该负责加载,以及如何连接所有部分?您应该将加载存储的逻辑放在将显示此存储的网格控制器中。我把它们放在afterrender事件的处理程序中。我刚开始使用MVC时,从未从Sencha那里找到关于这一点的明确答案,但我可以告诉你我成功地为一些应用程序做了些什么 我根据商店的使用方式创建和加载它们。对我来说,这似乎分为三类: 应用于整个应用程

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


mvc应用程序的哪个部分应该负责加载,以及如何连接所有部分?

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

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

我根据商店的使用方式创建和加载它们。对我来说,这似乎分为三类:

  • 应用于整个应用程序的商店

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

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

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

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

    属于上述第一类的存储将进入此“主”控制器的
    存储
    阵列。如果这些存储不依赖于另一个存储,那么我只需让它们
    自动加载: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'
    }
    
    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();
        });
    });
    
    举一个例子,两个商店都属于第一类,其中一个商店相互依赖:

    在我的一个应用程序中,我有一个动态的用户权限数,当用户登录到该应用程序时,我需要获取不同的权限并修改
    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();
    
    var grid = Ext.widget('unicornweight', {
        unicornName: someUnicornNameVariable
    });
    
    myTabPanel.add(grid);
    
    有时,视图还依赖于正在加载的存储。例如,我的主菜单项由数据库表确定,在这种情况下,我将以相同的方式包括一个
    onLoad
    侦听器(在控制器的
    init
    函数中):

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

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

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

    然后是相同的基本概念,一些是
    自动加载:true
    如果依赖于其他商店的数据,则有些不是

    对于非
    自动加载:true
    的对象,它们被加载到控制器的
    init
    函数中的某个位置,或者作为触发某个事件的结果

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

    在这里,我可能反对MVC粒度,但是对于应用于视图的单个实例的存储来说,没有比应用于视图本身更好的地方了

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

    例如,假设您有一个
    MyApp.view.UnicornWeightGrid
    ,它扩展了
    gridpanel
    ,并显示了一只独角兽随时间的累进重量。用户可以打开域中所有独角兽的
    UnicornWeightGrid
    ,以进行比较和交叉参考。
    UnicornWeightStore
    的不同实例与
    unicornweightsgrid
    的实例一样多

    视图可以这样定义:

    {
        xtype: 'combobox',
        allowBlank: false,
        forceSelection: true,
        store: Ext.getStore('SomeReferenceStore'),
        queryMode: 'local', // this makes sure the store doesn't reload
        valueField: 'id',
        displayField: 'name'
    }
    
    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 user = Ext.getStore('CurrentUser').first();
    
    var grid = Ext.widget('unicornweight', {
        unicornName: someUnicornNameVariable
    });
    
    myTabPanel.add(grid);
    
    在视图中定义的存储上需要的任何
    onLoad
    侦听器,我也会附加到视图中。所以我真的不需要其他地方的推荐人

    尽管如此,这绝不是开设店铺的唯一方法

    我发现在创建几个不同的ExtJS“MVC”应用程序时,这是一致处理商店的最可行的方法,但在“特殊”情况下,我有时也会采取不同的方法


    您应该记住,“MVC”是一种非常松散的设计模式,在我使用过的几乎每个框架中,它的定义和实现都是不同的。所以你几乎可以做任何对你最有利的事情。

    这是一个多么令人惊讶的答案。非常感谢!:)我的意思是我有自己的想法,但这只是非常全面和措辞得体。为什么我不能投票不止一次?