ExtJS 6 Modern版无限滚动ComboBox实现报错求助
在ExtJS 6 Modern版实现无限滚动ComboBox(无需替换为Grid)
我之前在ExtJS 6.5.2 Modern版里折腾过这个需求,确实会遇到Uncaught TypeError: a.setExtraKeys is not a function这个报错——原因是默认的BoundList(ComboBox的选择器)会调用Store的setExtraKeys方法,但Virtual Store原生没有这个方法。不过不用把选择器改成Grid,只要做几个小调整就能解决,下面是亲测有效的方案:
1. 扩展Virtual Store解决报错
我们给Virtual Store添加一个setExtraKeys的简单实现,让BoundList的逻辑能正常执行:
Ext.define('MyApp.data.VirtualStore', { extend: 'Ext.data.VirtualStore', // 给Virtual Store添加缺失的setExtraKeys方法 setExtraKeys: function(keys) { this.extraKeys = keys; // 简单存储即可,不需要额外逻辑 } });
之后ComboBox的Store就使用这个自定义的VirtualStore类型。
2. 优化BoundList的无限滚动配置
你已经配置了floatedPicker为BoundList,但还有几个细节要调整,确保无限滚动和交互正常:
floatedPicker: { xtype: 'boundlist', infinite: true, // 导航模型只在选择器显示时启用,避免和输入框的键盘事件冲突 navigationModel: { type: 'boundlist', disabled: true, enableKeyEvents: true }, scrollToTopOnRefresh: false, // 刷新时不滚动到顶部,保持当前浏览位置 loadingHeight: 70, // 加载状态下的占位高度 maxHeight: 300, floated: true, axisLock: true, hideAnimation: null, listeners: { // 选择器显示前,如果Store未加载则触发初始加载 beforeShow: function(list) { const store = list.getStore(); if (store && !store.isLoaded()) { store.load(); } }, // 滚动到底部附近时,触发加载下一页 scrollend: function(list, scroller) { const store = list.getStore(); // 距离底部100px时触发加载,可根据需求调整阈值 if (scroller.position.y >= scroller.maxPosition.y - 100) { store.nextPage(); } } } }
3. 完整的ComboBox示例
把上面的配置整合起来,再加上必要的ComboBox属性:
Ext.create('Ext.field.ComboBox', { renderTo: Ext.getBody(), fieldLabel: '无限滚动选择', displayField: 'name', // 替换为你的实际显示字段 valueField: 'id', // 替换为你的实际值字段 queryMode: 'remote', // 必须设为remote,配合远程分页逻辑 store: { type: 'myvirtualstore', // 使用我们自定义的VirtualStore pageSize: 20, // 每页加载数量,根据需求调整 proxy: { type: 'ajax', url: '/your/api/endpoint', // 替换为你的后端接口地址 reader: { type: 'json', rootProperty: 'data', // 接口返回的数据根节点 totalProperty: 'total' // 接口返回的总记录数字段 } } }, floatedPicker: { xtype: 'boundlist', infinite: true, navigationModel: { type: 'boundlist', disabled: true, enableKeyEvents: true }, scrollToTopOnRefresh: false, loadingHeight: 70, maxHeight: 300, floated: true, axisLock: true, hideAnimation: null, listeners: { beforeShow: function(list) { const store = list.getStore(); if (store && !store.isLoaded()) { store.load(); } }, scrollend: function(list, scroller) { const store = list.getStore(); if (scroller.position.y >= scroller.maxPosition.y - 100) { store.nextPage(); } } } } });
额外注意事项
- 后端接口必须支持分页,并且返回
total字段(总记录数),这样Virtual Store才能正确计算分页信息。 - 如果需要支持输入搜索(ComboBox的查询功能),可以在ComboBox的
beforequery事件里设置Store的查询参数,然后重新加载第一页:listeners: { beforequery: function(queryPlan) { const store = this.getStore(); store.getProxy().setExtraParams({ keyword: queryPlan.query }); store.loadPage(1); return false; // 阻止默认查询逻辑,使用自定义分页加载 } } - 测试时记得检查滚动到底部是否触发加载,以及选择器显示时的初始加载是否正常。
内容的提问来源于stack exchange,提问作者Zoti
相关产品推荐
相关产品推荐

