Ext JS:TabPanel渲染无限网格太快了

比方说,我有一个TabPanel添加到它的两个组件。 每个组件都包含一个无限网格。 每个无限网格从服务调用中加载其数据,每组数据包含2000条logging。 将组件添加到TabPanel之后,我们使用setActiveTab将每个组件设置为活动选项卡。 我们首先将第二个选项卡设置为活动选项卡,然后设置第一个选项卡。 当页面加载时,第一个标签被选中,正如我们所预期的那样。

当看第一个标签时,一切看起来都很好……我们可以无限滚动,sorting,隐藏列等。但是,如果我们切换到第二个标签,我们看到它已经部分加载,而且我们不能滚动过去已经加载,隐藏列,sorting等xlogging。这几乎就像使用setActiveTab有点过早提交网格…好像商店没有完全加载,但无论如何该标签呈现。 (这是我假设的问题是)

我确实有代码,但需要一些工作来重现(因为你需要一个服务调用)。 我在Node.js应用程序中使用CompoundJS,所以创buildtesting用例非常简单。 如果您有权访问数据库,并且可以快速进行服务调用,那么只需修改我的Ext JS代码,但是如果您想使用Node.js,则可以尝试以下操作:

Ext JS 4.2.1

Ext.onReady(function() { var tabPanel = Ext.create('Ext.tab.Panel', { width: 400, height: 400, renderTo: Ext.getBody() }); Ext.define('myGrid', { extend: 'Ext.grid.Panel', constructor: function(config) { this.columns = config.columns; this.store = Ext.create('Ext.data.Store', { fields: config.fields, buffered: true, leadingBufferZone: 20, pageSize: 50, proxy: { type: 'ajax', url: '/getData?id=' + config.id, reader: { totalProperty: 'totalCount', type: 'json', root: 'root' } }, autoLoad: true }); this.id = config.id; this.callParent(); } }); var grid1 = Ext.create('myGrid', { id: 'blah', columns: [{ text: 'one', dataIndex: 'one' }, { text: 'two', dataIndex: 'two' }, { text: 'three', dataIndex: 'three' }], fields: ['one', 'two', 'three'], title: 'grid1' }); var grid2 = Ext.create('myGrid', { id: 'bleh', columns: [{ text: 'one', dataIndex: 'one' }, { text: 'two', dataIndex: 'two' }, { text: 'three', dataIndex: 'three' }], fields: ['one', 'two', 'three'], title: 'grid2' }); var c1 = []; c1.items = [grid1]; c1.title = "BLAH"; c1.layout = 'fit'; var c2 = []; c2.items = [grid2]; c2.title = "BLEH"; c2.layout = "fit"; tabPanel.add([c1, c2]); tabPanel.setActiveTab(1); tabPanel.setActiveTab(0); }); 

Node.js代码

 compound init test && cd test npm install compound gs testcontroller 

app / controllers / testcontrollers_controller.jsreplace为:

 load('application'); action('getData', function(data) { var query = data.req.query; var id = query.id; var page = query.page; var pushObj; if (id === 'blah') { pushObj = { one: 'bye', two: 'goodbye', three: 'auf wiedersehen' }; } else { pushObj = { one: 'hi', two: 'hello', three: 'guten tag' }; } var obj = []; for (var i = 0; i < 50; i++) { obj.push(pushObj); } send({ totalCount: 2000, root: obj, page: page }); }); 

config / routes.js中 ,删除testcontroller的map.resources行,并添加:

 map.get('getData', 'testcontrollers#getData'); 

public / index.html中 ,使其成为一个通用的HTML文件,并添加到您的链接到Ext JS和我的上面的Ext JS代码。

现在,一旦你完成了这一切,你应该能够重现我的问题。 第一个选项卡将打开,并很好,但第二个选项卡只加载第一个x数量的logging,并不能正常工作。 我相信这是由于商店没有完全加载setActiveTab时被激发,这使得渲染加载一个公正的商店。

我想知道的是,我怎样才能使这个工作正常? 我试过等待商店加载,然后将其添加到选项卡,但这仍然给我不一致的结果,以及尝试等待网格停止呈现,但仍然,我得到不一致的结果…不一致意思,有时网格一路载入,选项卡是好的,但其他时间,我得到一个无法读取属性的'长度'未定义在ext-all-dev.js:135,786 …这使得它看起来像store没有完全加载,因为该行包含对records.length的引用。

如果有人有任何想法,我很乐意听到他们! 从Sencha论坛交叉发表。

编辑:感谢@ SOLO,我能够重现在这个例子中的问题。 如果您启用了Firebug,您将会看到关于未定义属性长度的错误,如上所述。

我将问题追踪到插件caching不正确的大小值,当它被隐藏。

这是一个可以解决这个问题的重写:

 /** * Prevents BufferedRenderer plugin to break when buffered views are * rendered or refreshed while hidden, like in a card layout. * * Tested with Ext 4.2.1 */ Ext.define('Ext.ux.Ext.grid.plugin.BufferedRenderer.HiddenRenderingSupport', { override: 'Ext.grid.plugin.BufferedRenderer' /** * Refreshes the view and row size caches if they have a value of 0 * (meaning they have probably been cached when the view was not visible). */ ,onViewResize: function() { if (this.rowHeight === 0) { if (this.view.body.getHeight() > 0) { this.view.refresh(); } } else { this.callParent(arguments); } } }); 

这就是说,我build议不要使用这个和不必要的膨胀你的代码库。

您应该以避免这种情况的方式组织您的代码。 这个问题是由于您在同一个执行框架中多次调用setActiveTab而创build的。 如果避免这种情况,Ext将自行正确处理这种情况。

作为一般原则,您应该尝试使您的Ext代码更具说明性… Ext体系结构相当期望您构build大的configuration对象来一次创build组件(允许primefacesDOM更新等),并使用方法稍后更新状态,以驱动组件的行为。

在您的情况下,您应该使用activeTab选项来设置初始选项卡,并且稍后在实际需要更改选项卡时仅调用setActiveTab 。 这将节省一些不必要的处理在初始化,也将解决您的渲染问题…

以下是你的代码应该是这样的:

 Ext.create('Ext.tab.Panel', { renderTo: Ext.getBody(), width: 400, height: 400, // Use this option to set the initial tab. activeTab: 2, // You don't need to overnest your grids into another Panel, you can add // them directly as children of the tab panel. items: [ // Ideally, you should give an xtype to your class, and add this to // avoid instantiating the object yourself... Thus giving Ext more // control on the rendering process, etc. Ext.create('myGrid', { id: 'blah', title: 'Bleh', columns: [{ text: 'one', dataIndex: 'one' }, { text: 'two', dataIndex: 'two' }, { text: 'three', dataIndex: 'three' }], fields: ['one', 'two', 'three'], title: 'grid1' }), Ext.create('myGrid', { id: 'bleh', title: 'Bleh', columns: [{ text: 'one', dataIndex: 'one' }, { text: 'two', dataIndex: 'two' }, { text: 'three', dataIndex: 'three' }], fields: ['one', 'two', 'three'], title: 'grid2' }) ] }); 

正如您所看到的,选项卡面板子项目在创build时设置,避免了使用add方法无用的处理。 同样, activeTab选项避免初始化面板在给定的状态,并立即改变它…稍后(在另一个执行框架,例如在button处理程序中),您可以使用setActiveTab而不会触发原始示例中显示的错误。