做报销系统的同事最近很烦:员工填"费用类别"时,有人手打"差旅费",有人写成"差旅 费",还有人直接填"交通"。月底一汇总,同一个类别裂成了七八种写法,财务对不上账。问题不出在人身上,而是表单把一道选择题当成了填空题。
为什么这个细节重要
在 Excel 里,大家早就习惯了数据验证带来的下拉选择:点开单元格,选项列出来,选一个就走。这套习惯迁移到 Web 应用时却经常断档——很多前端表格只能让用户老老实实敲字符串,结果是录入慢、脏数据多,清洗成本全部转嫁给下游。
对产品经理来说,这是录入体验的口碑问题;对开发者来说,这意味着要么自己造一个弹层下拉,再去处理定位、滚动、键盘导航一堆细节。SpreadJS 作为纯前端的 JavaScript 电子表格控件,把这件事收敛成了四种内置方案,按需挑一种就行。
四条内置路径
第一种:组合框单元格类型。 用 new GC.Spread.Sheets.CellTypes.ComboBox() 创建实例,items() 设置选项,每个选项可以带 text 和 value 两个字段——界面上显示"华东大区",存进数据模型的却是区域编码。再用 setCellType 挂到单元格上。它还支持 editable(true) 放行列表外的自定义输入,maxDropDownItems 控制下拉每页显示几项。
第二种:数据验证序列。 一行核心代码:createListValidator('华东,华南') 配合 setDataValidator。这与 Excel 的数据验证同源,胜在最简单,但选项只能是纯文本,做不到显示与存储分离。
第三种:样式下拉菜单。 给 Style 配置 cellButtons 加一个下拉按钮(命令为 openList),再用 dropDowns 声明 DropDownType.list 类型的列表。它的扩展空间最大:选项支持分组、级联,打开 multiSelect 还能变成多选。
第四种:表单控件。 通过 shapes.addFormControl 与 FormControlType.comboBox 在画布上放一个独立于单元格的组合框,inputRange 指向单元格区域作为选项来源,cellLink 可以把选中索引同步回某个单元格——基本复刻了 Excel 表单控件的手感。
// 1. ComboBox 单元格类型
var combo = new GC.Spread.Sheets.CellTypes.ComboBox();
combo.items([{ text: '华东', value: 1 }, { text: '华南', value: 2 }]);
sheet.setCellType(2, 1, combo);
// 2. 数据验证序列
sheet.setDataValidator(2, 3,
GC.Spread.Sheets.DataValidation.createListValidator('华东,华南'));
// 3. 样式下拉菜单
var style = new GC.Spread.Sheets.Style();
style.cellButtons = [{ imageType: GC.Spread.Sheets.ButtonImageType.dropdown,
command: 'openList', useButtonStyle: true }];
style.dropDowns = [{ type: GC.Spread.Sheets.DropDownType.list,
option: { items: [{ text: '华东', value: 1 }] } }];
sheet.setStyle(2, 5, style);
// 4. 表单控件 ComboBox
var fc = sheet.shapes.addFormControl('comboBox',
GC.Spread.Sheets.Shapes.FormControlType.comboBox, 100, 50, 200, 30);
var opt = fc.options();
opt.inputRange = 'K1:K2';
fc.options(opt);
怎么选,能用到哪里
简单枚举、不在意样式,选数据验证序列;要求"显示文本与实际值分离",用组合框单元格类型或样式下拉;需要多选、分组这类复杂交互,样式下拉的 multiSelect 和嵌套 items 最合适;想在报表角落放一个独立的筛选器,就用表单控件。
这套思路可以直接推广:物料分类、会计科目、审批状态、订单标签,本质上都是同一道选择题,区别只在选项从哪来、要不要多选。
给开发者的关键词
CellTypes.ComboBox、items、setCellType、DataValidation.createListValidator、setDataValidator、Style.cellButtons、dropDowns、openList、DropDownType.list、shapes.addFormControl、FormControlType.comboBox、inputRange。
小结
下拉列表看着只是个小控件,背后其实是数据规范化的第一道闸门。SpreadJS 把四种成熟做法放进了同一个组件,各自的适用边界也清楚,开发者按场景取用即可,不必再为弹层定位、键盘操作这些细节重复造轮子。