ExtJS 4-重用MVC架构中的组件

| 我有一个用户列表,如果单击此列表中的一个项目,则会打开一个窗口。每个用户都使用同一窗口,并且可以同时打开多个窗口。该窗口显示用户信息,因此对于这些组件,我具有相同的商店和相同的型号。 但是,如果我在特定窗口中加载数据,则在所有其他打开的窗口中加载相同的数据。
Ext.define(\'Cc.view.absence.Grid\', {
  extend: \'Ext.grid.Panel\',
  alias: \'widget.absencegrid\',

  border:false,

  initComponent: function() {
    Ext.apply(this, {
      store: Ext.create(\'Ext.data.Store\', {
        model: \'Cc.model.Absence\',
        autoLoad: false,
        proxy: {
          type: \'ajax\',
          reader: {
            type: \'json\'
          }
        }
      }),
      columns: [
        {header: \'Du\', dataIndex: \'startdate\', flex: 3, renderer: this.formatDate},
        {header: \'Au\', dataIndex: \'enddate\', flex: 3, renderer: this.formatDate},
        {header: \'Exercice\', dataIndex: \'year\', align: \'center\', flex: 1},
        {header: \'Statut\', xtype:\'templatecolumn\', tpl:\'<img src=\"../images/status-{statusid}.png\" alt=\"{status}\" title=\"{status}\" />\', align: \'center\', flex: 1},
        {header: \'Type d\\\'absence\', dataIndex: \'absencetype\', align: \'center\', flex: 2},
        {header: \'Commentaires\', dataIndex: \'comment\', flex: 6}
      ],
      dockedItems: [{
        xtype: \'toolbar\',
        dock: \'top\',
        items: [
          { xtype: \'tbfill\'},
          { xtype: \'button\', text: \'Rafraichir\', action: \'refresh\', iconCls: \'item-rafraichir\' }
        ]
      }]
    });

    this.callParent(arguments);
  },

  formatDate: function(date) {
    if (!date) {
      return \'\';
    }
    return Ext.Date.format(date, \'l d F Y - H:i\');
  }

});
我的控制器:
Ext.define(\'Cc.controller.Absences\', {
  extend: \'Ext.app.Controller\',

  models: [\'Absence\', \'AbsenceHistory\'],

  views: [],

  refs: [
    { ref: \'navigation\', selector: \'navigation\' },
    { ref: \'tabPanel\', selector: \'tabpanel\' },
    { ref: \'absencePanel\', selector: \'absencepanel\' },
    { ref: \'refreshButton\', selector: \'absencepanel button[action=refresh]\'},
    { ref: \'absenceGrid\', selector: \'absencegrid\' },
    { ref: \'absenceHistory\', selector: \'absencehistory\' },
  ],

  init: function() {
    this.control({
      \'absencepanel button[action=refresh]\': {
        click: this.onClickRefreshButton
      },
      \'absencegrid\': {
        selectionchange: this.viewHistory
      },
      \'absencegrid > tableview\': {
        refresh: this.selectAbsence
      },
    });
  },

  selectAbsence: function(view) {
    var first = this.getAbsenceGrid().getStore().getAt(0);
    if (first) {
      view.getSelectionModel().select(first);
    }
  },

  viewHistory: function(grid, absences) {
    var absence = absences[0],
      store = this.getAbsenceHistory().getGrid().getStore();
    if(absence.get(\'id\')){
      store.getProxy().url = \'/absence/\' + absence.get(\'id\') +\'/history\';
      store.load();
    }
  },

  onClickRefreshButton: function(view, record, item, index, e){
    var store = this.getAbsenceGrid().getStore();
    store.load();
  },
});
其他控制器,仅创建一个不存在的实例。Panel:
Ext.define(\'Cc.controller.Tools\', {
  extend: \'Ext.app.Controller\',

  stores: [\'Tools\', \'User\' ],

  models: [\'Tool\'],

  views: [],

  refs: [
    { ref: \'navigation\', selector: \'navigation\' },
    { ref: \'tabPanel\', selector: \'tabpanel\' },
    { ref: \'toolList\', selector: \'toollist\' },
    { ref: \'toolData\', selector: \'toollist dataview\' }
  ],

  init: function() {
    this.control({
      \'toollist dataview\': {
        itemclick: this.loadTab
      },
    });
  },

  onLaunch: function() {
    var dataview = this.getToolData(),
        store = this.getToolsStore();

    dataview.bindStore(store);
  },

  loadTab: function(view, record, item, index, e){
    var tabPanel = this.getTabPanel();
    switch (record.get(\'tab\')) {
      case \'absences\':
        if(Ext.getCmp(\'absence-panel\')){
          tabPanel.setActiveTab(Ext.getCmp(\'absence-panel\'));
        }
        else {
          var panel = Ext.create(\'Cc.view.absence.Panel\',{
            id: \'absence-panel\'
          }),
              store = panel.getGrid().getStore();
          panel.enable();
          tabPanel.add(panel);
          tabPanel.setActiveTab(panel);
          store.getProxy().url = \'/person/\' + this.getUserId() +\'/absences\';
          store.load();
        }
      break;

      default: 
      break;
    }
  },

  getUserId: function(){
    var userStore = this.getUserStore();
    var id = userStore.first().get(\'id\')
    return id;
  }
});
另一个控制器,它创建许多不存在的实例。
Ext.define(\'Cc.controller.Agents\', {
  extend: \'Ext.app.Controller\',

  stores: [\'Agents\'],

  models: [\'Agent\', \'Absence\', \'AbsenceHistory\'],

  views: [\'agent.List\', \'agent.Window\', \'absence.Panel\', \'absence.Grid\', \'absence.History\'],
  refs: [
    { ref: \'agentList\', selector: \'agentlist\' },
    { ref: \'agentData\', selector: \'agentlist dataview\' },
    { ref: \'agentWindow\', selector: \'agentwindow\' },
  ],

  init: function() {
    this.control({
      \'agentlist dataview\':{
        itemclick: this.loadWindow
      },
    });
  },

  onLaunch: function() {
    var dataview = this.getAgentData(),
        store = this.getAgentsStore();
    dataview.bindStore(store);
  },

  loadWindow: function(view, record, item, index, e){
    if(!Ext.getCmp(\'agent-window\'+record.get(\'id\'))){
      var window = Ext.create(\'Cc.view.agent.Window\', {
        title: \'À propos de \'+record.get(\'firstname\')+\' \'+record.get(\'lastname\'),
        id: \'agent-window\'+record.get(\'id\')
      }),
          tabPanel = window.getTabPanel();
          absencePanel = window.getAbsencePanel();
          store = absencePanel.getGrid().getStore();

      absencePanel.enable();
      tabPanel.add(absencePanel);
      tabPanel.setActiveTab(absencePanel);
      store.getProxy().url = \'/person/\' + record.get(\'id\') +\'/absences\';
      store.load();
    }
    Ext.getCmp(\'agent-window\'+record.get(\'id\')).show();
  }
});
和missing.Panel视图,missing.Grid的容器:
Ext.define(\'Cc.view.absence.Panel\', {
    extend: \'Ext.panel.Panel\',
    alias: \'widget.absencepanel\',

  title: \'Mes absences\',
  iconCls: \'item-outils\',
  closable: true,
  border: false,
  disabled: true,
  layout: \'border\',

  initComponent: function() {
    this.grid = Ext.create(\'Cc.view.absence.Grid\', {
      region: \'center\'
    });
    this.history = Ext.create(\'Cc.view.absence.History\', {
      region: \'south\',
      height: \'25%\'
    });
        Ext.apply(this, {
      items: [
        this.grid,
        this.history
      ]
    });

        this.callParent(arguments);
    },

  getGrid: function(){
    return this.grid;
  },

  getHistory: function(){
    return this.history;
  }
});
    
已邀请:
是。这是我正在做什么的更多详细说明。希望您已经阅读了完整的论坛。仍然有一个我们不清楚的信息。那就是在控制器中使用\“ stores \”属性的确切用法。恕我直言,Sencha团队应使用复杂的示例对MVC进行更详细的说明。 是的,您新发布的内容是正确的。创建新视图后,请创建商店的新实例!现在,从论坛讨论中,人们开始争论MVC。我一定会和斯蒂芬克一起去。我在这里所做的就是将新的store实例注入我的视图。而且我忽略了控制器的5属性。 这是一个例子: 这是我的看法。我在选项卡面板上显示的面板(包含用户个人资料信息):
Ext.define(\'Dir.view.profile.View\' ,{
    extend: \'Ext.panel.Panel\',
    alias : \'widget.profileview\',
    title : \'Profile\',
    profileId: 1,   // default and dummy value
    initComponent: function() {

        // configure necessary stuff, I access my store etc here..       
        // console.log(this.profileStore);
        this.callParent(arguments);         
    },
    // Other view methods goes here
});
现在,看一下我的控制器:
Ext.define(\'Dir.controller.Profile\', {
    extend: \'Ext.app.Controller\',
    //stores: [\'Profile\'],   --> Note that I am NOT using this!
    refs: [     
        {ref:\'cp\',selector: \'centerpane\'}
    ],
    views: [\'profile.View\'],
    init: function() {
        // Do your init tasks if required
    },  
    displayProfile: function(selectedId) {

            // create a new store.. pass your config, proxy url etc..
        var store = Ext.create(\'Dir.store.Profile\',{profileId: selectedId});

        console.log(\'Display Profile for ID \' + selectedId);    

        // Create instance of my view and pass the new store
        var view = Ext.widget(\'profileview\',{profileId: selectedId,profileStore: store});

        // Add my new view to centeral panel and display it...
        this.getCp().add(view);
        this.getCp().setActiveTab(view);
    }
});
我的
displayProfile()
是从某些事件侦听器(菜单,树等)中调用的,并传递一个ID。我的控制器使用此ID来设置新的商店和视图。我希望上面的代码能使您清楚地了解我昨天所说的内容。 在您的控制器中,您将必须添加“ 9”,以便ExtJS知道您拥有这样的商店。这是因为我们没有使用
stores
属性。 现在,您可以在其他地方重用这些创建的商店,可以将它们添加到StoreManager。这样,您可以在任何地方访问创建的商店,添加和删除商店。但这会带来管理存储实例的开销。 为什么要共享具有不同视图的商店的同一实例?当您有新视图时,请创建商店的新实例。这样一来,刷新后的其他窗口将不会显示更新的数据。     

要回复问题请先登录注册