ExtJS Grid 呈现的行数超过了 pagesize 中指定的行数
Posted
技术标签:
【中文标题】ExtJS Grid 呈现的行数超过了 pagesize 中指定的行数【英文标题】:ExtJS Grid renders more rows than specified in pagesize 【发布时间】:2013-03-27 14:05:06 【问题描述】:我已经根据 Sencha 给出的例子实现了一个无限网格。基本上,代理使用 jsonp 获取 json 文件并填充网格。我希望网格大小为 10,并且我希望代理仅在用户向下滚动到第 10 条记录时才发出后续请求。每条记录在网格视图中垂直占用足够的空间,不滚动只能看到大约 5 条记录(在我的 14 英寸笔记本电脑上,分辨率为 1366 x 768)。我已将页面大小设置为 10,我的期望是只有当我向下滚动到可见记录之外时网格才会刷新。但是,即使不滚动,网格也会通过发出 5 个单独的请求来加载所有数据(总共 50 条记录)。代码如下:
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.grid.plugin.BufferedRenderer'
]);
Ext.onReady(function()
Ext.define('ContentModel',
extend : 'Ext.data.Model',
fields : [ 'content_id', 'content' ],
idProperty: 'content_id'
);
var store = Ext.create('Ext.data.Store',
id : 'store',
model : 'ContentModel',
buffered: true,
pageSize: 10,
proxy :
type : 'jsonp',
url : 'http://website.com/Top1.json',
reader:
root: 'contents',
totalProperty: 'totalCount'
,
autoLoad : true
);
var grid = Ext.create('Ext.grid.Panel',
renderTo : Ext.getBody(),
width : '100%',
height : '100%',
title : 'Reader Panel',
id : 'reader',
store : store,
columns : [
id : 'content_id',
text : 'Content ID',
dataIndex : 'content_id',
width : '10%'
,
id : 'content',
text : 'Content',
dataIndex : 'content',
width : '90%'
]
);
Ext.define('JSONP Proxy',
override: 'Ext.data.proxy.JsonP',
buildUrl: function(request)
var me = this, url = this.getUrl(request);
console.log(url);
request.url = 'http://website.com/Top' + request.params.page + '.json';
return me.callParent([request]);
);
);
而json文件的内容是:
Top1.json:
Ext.data.JsonP.callback1("totalCount":"50", "contents":["content_id" : 1, "content" : "<div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br>","content_id" : 2, "content" : "<div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br>","content_id" : 3, "content" : "<div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br>","content_id" : 4, "content" : "<div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br>","content_id" : 5, "content" : "<div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br>","content_id" : 6, "content" : "<div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br>","content_id" : 7, "content" : "<div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br>","content_id" : 8, "content" : "<div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br>","content_id" : 9, "content" : "<div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br>","content_id" : 10, "content" : "<div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br><div> Hello World 1</div><br>"]);
其他 json 文件遵循相同的格式,具有唯一的内容 ID,并具有正确的回调(callback2、callback3、callback4 和 callback5)。
谁能告诉我为什么所有 5 个 jsonp 请求都被立即触发,而不是等待我滚动?
谢谢, 普拉塔普
【问题讨论】:
【参考方案1】:感谢大家为我指明正确的方向。所以,这就是最终奏效的方法:
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.grid.plugin.BufferedRenderer'
]);
Ext.onReady(function()
Ext.define('ContentModel',
extend : 'Ext.data.Model',
fields : [ 'content_id', 'content' ],
idProperty: 'content_id'
);
var store = Ext.create('Ext.data.Store',
id : 'store',
model : 'ContentModel',
buffered: true,
pageSize: 10,
trailingBufferZone: 5,
leadingBufferZone: 5,
purgePageCount: 0,
scrollToLoadBuffer: 10,
proxy :
type : 'jsonp',
url : 'http://website.com/Top' + 0 + '.json',
reader:
root: 'contents',
totalProperty: 'totalCount'
,
autoLoad : true
);
var grid = Ext.create('Ext.grid.Panel',
renderTo : Ext.getBody(),
width : '100%',
height : '100%',
title : 'Reader Panel',
id : 'reader',
store : store,
plugins : [
ptype: 'bufferedrenderer',
trailingBufferZone: 5,
leadingBufferZone: 5,
scrollToLoadBuffer: 10,
onViewResize: function(view, width, height, oldWidth, oldHeight)
// Only process first layout (the boxready event) or height resizes.
if (!oldHeight || height !== oldHeight)
var me = this,
newViewSize,
scrollRange;
// View has rows, delete the rowHeight property to trigger a recalculation when scrollRange is calculated
if (view.all.getCount())
// We need to calculate the table size based upon the new viewport size and current row height
delete me.rowHeight;
// If no rows, continue to use the same rowHeight, and the refresh handler will call this again.
// Calculates scroll range. Also calculates rowHeight if we do not have an own rowHeight property.
// That will be the case if the view contains some rows.
scrollRange = me.getScrollHeight();
//newViewSize = Math.ceil(height / me.rowHeight) + me.trailingBufferZone + me.leadingBufferZone;
newViewSize = 18;
me.viewSize = me.setViewSize(newViewSize);
me.stretchView(view, scrollRange);
],
columns : [
id : 'content_id',
text : 'Content ID',
dataIndex : 'content_id',
width : '10%'
,
id : 'content',
text : 'Content',
dataIndex : 'content',
width : '90%'
]
);
Ext.define('JSONP Proxy',
override: 'Ext.data.proxy.JsonP',
buildUrl: function(request)
var me = this, url = this.getUrl(request);
console.log(url);
request.url = 'http://website.com/Top' + request.params.page + '.json';
return me.callParent([request]);
);
);
诀窍是在 store 和 grid 的 bufferedrenderer 插件中正确设置缓冲区设置,并覆盖插件的 onViewResize 方法。 bufferedrenderer 的 ViewSize 属性是根据 rowheight 计算的,由于某种原因,它始终是其默认值 21,因此导致 ViewSize 为 60,大于服务器中的记录总数 (50) .这导致立即获取所有行。一旦我将 viewsize 属性覆盖为 18,viewsize 就会相应地发生变化,现在我第一次只获取了 30 条记录。并且按需加载在滚动时也很完美:)
【讨论】:
想知道为什么需要使用这个 bufferedrenderer 插件?如果您在此处查看示例 - docs.sencha.com/ext-js/4-1/#!/example/grid/… 或此处 - docs.sencha.com/ext-js/4-2/#!/example/grid/… 未使用此类插件。您的视图是否经常调整大小? 我使用它是因为 4.2 中无限网格是这样实现的。您共享的第二个链接确实使用了缓冲渲染器插件。不,我的视图不会经常手动调整大小,但我猜每次刷新视图时都会计算视图大小,这会在用户上下滚动时经常发生。 不确定我们是否在同一页面上,因为当我查看 JS 文件的代码时 - docs.sencha.com/ext-js/4-2/extjs-build/examples/grid/… - 我发现该插件仅通过 'require' 包含但它有没有按照您的方式使用 ptype 在网格对象中进行配置。 嗯,我的理解是你需要包含插件才能缓冲工作。 leadingbufferzone、trailingbufferzone 等属性现在是 bufferedrender 插件的一部分 - pagingscroller 插件现已从 4.2 中删除【参考方案2】:您需要为leadingBufferZone 和trailingBufferZone 设置正确的值,以获得正确的记录数。
【讨论】:
谢谢,我确实玩过这两个参数。这是我最近尝试的设置 - pageSize: 10, trailingBufferZone: 5,leadingBufferZone: 5, purgePageCount: 0, scrollToLoadBuffer: 10, 它仍然没有修复它:/【参考方案3】:您正在使用buffered
配置。如果启用buffered
,则默认情况下,存储会再加载 5 个页面到预取缓存中。为了改变prefectched页面的数量,使用purgePageCount config。
【讨论】:
感谢您的指点。但是,将 purgePageCount 设置为 0 也不能解决问题。奇怪的是,将 purgePageCount 设置为 1 到 4 之间的任何值都会导致一个空网格。以上是关于ExtJS Grid 呈现的行数超过了 pagesize 中指定的行数的主要内容,如果未能解决你的问题,请参考以下文章