You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:10:32