Skip to content

选择输入

本页包括 Select、TreeSelect、Radio、Checkbox、Switch 和 TagSelect。选择字段的核心是明确“选项来源、控件值、业务存储值、只读文本”四者的关系。

通用 options 格式

推荐:标准对象数组

ts
options: [
  { label: "管理员", value: "admin", disabled: false },
  { label: "普通用户", value: "user" },
];

DefaultOptionType 明确声明 labelvaluechildrendisabled,并允许携带业务附加字段。children 主要服务树形数据或底层组件场景。

其他来源对比

ts
// 原始值数组:label 与 value 都是元素本身
options: ['draft', 'published']

// 对象字典:键是 value,值是 label
options: { draft: '草稿', published: '已发布' }

// Ref:外部更新后选项响应
options: statusOptions

// 函数或 Promise:收到 effectData
options: ({ current }) => api.getOptions(current.category)

// 全局字典
dictName: 'article_status'

标准对象数组语义最明确。原始值数组配置 valueToNumber: true 时会改用数字下标作为 value;不要把它理解为对元素做 Number() 转换。

通用值转换属性

属性类型默认值结果适合场景
valueToNumberbooleanfalse选项 value 归一化为 number;原始数组使用下标后端要求数字枚举
labelAsValuebooleanfalse字段直接保存选项 label值与文案完全一致的简单接口
labelFieldstringvalue 存 field,label 另存一个字段同时提交 ID 和名称
stringifyValuebooleanfalse多选数组转逗号字符串接口使用逗号分隔值
tagViewerboolean/object/array/function自动控制只读 Tag 显示表格、详情状态展示

三种存储方式对比

ts
// 1. 只存 value:{ departmentId: 12 }
{ type: 'Select', field: 'departmentId', options }

// 2. 直接存 label:{ department: '研发中心' }
{ type: 'Select', field: 'department', labelAsValue: true, options }

// 3. value + label:{ departmentId: 12, departmentName: '研发中心' }
{
  type: 'Select',
  field: 'departmentId',
  labelField: 'departmentName',
  options,
}

第三种最适合详情回显和提交快照。labelField 是同级数据路径,见Schema 与数据模型

fieldNames

后端已有扁平选项字段时可通过 Select 的 attrs.fieldNames 映射:

ts
{
  type: 'Select',
  field: 'userId',
  options: [{ userName: '张三', userId: 8 }],
  attrs: {
    fieldNames: { label: 'userName', value: 'userId' },
  },
}

组件会先归一化为标准 label/value 再交给底层控件,表单和只读显示保持一致。全局 dictApi 仍应直接返回标准格式。

Select

ts
{
  type: 'Select',
  field: 'roles',
  label: '角色',
  options: roleOptions,
  attrs: {
    mode: 'multiple',
    allowClear: true,
    showSearch: true,
    optionFilterProp: 'label',
  },
}

默认占位符为“请选择 + label”,默认按 label 过滤。attrs 继承 Ant Design Vue SelectProps,如 modeallowClearshowSearchfilterOptionfieldNamesmaxTagCountloading

远程搜索

ts
{
  type: 'Select',
  field: 'userId',
  label: '用户',
  attrs: {
    showSearch: true,
    filterOption: false,
  },
  options: (_effectData, keyword) => api.searchUsers(keyword),
}

showSearch 开启、options 是函数且没有显式 onSearch 时,组件约以 600ms 尾部节流调用 options(effectData, keyword)

ts
// 完全接管关键词与加载状态
onSearch: ({ current }, keyword) => {
  current.lastKeyword = keyword;
  loadOptions(keyword);
};

显式 onSearch 后不会自动用关键词调用 options

TreeSelect

TreeSelect 使用 treeData,不走扁平 options 归一化:

ts
{
  type: 'TreeSelect',
  field: 'orgId',
  labelField: 'orgName',
  label: '组织',
  treeData: ({ formData }) => api.getOrgTree(formData.tenantId),
  attrs: {
    treeCheckable: false,
    allowClear: true,
    fieldNames: { label: 'name', value: 'id', children: 'children' },
  },
}
属性类型默认值说明
treeDataarray/function[]数组、返回数组的函数或 Promise 函数
labelFieldstring同步保存选择标签;多选时保存标签数组
attrsobject{}TreeSelectProps,如 multipletreeCheckabletreeDefaultExpandAll

字段值形态受 multipletreeCheckablelabelInValue 等底层属性影响,使用前应与接口类型对齐。

Radio

Radio 对应 Radio.Group,字段保存单个 value:

ts
{
  type: 'Radio',
  field: 'level',
  label: '等级',
  options: levelOptions,
  attrs: {
    optionType: 'button',
    buttonStyle: 'solid',
  },
}

专属 attrs 是 RadioGroupProps;支持通用 optionsdictName、值转换和 labelField

Checkbox

Checkbox 对应 Checkbox.Group,字段通常是 value 数组:

ts
{
  type: 'Checkbox',
  field: 'permissions',
  labelField: 'permissionNames',
  label: '权限',
  options: permissionOptions,
  stringifyValue: true,
}

默认保存数组;stringifyValue 保存逗号字符串;labelField 保存对应 label 数组。单个布尔状态使用 Switch,而不是无 options 的 Checkbox。

Switch

布尔模式

ts
{ type: 'Switch', field: 'enabled', label: '启用' }

值未定义时会写入默认未选中值;defaultChecked 通过 attrs.defaultChecked: true 改为默认选中。

业务枚举模式

ts
{
  type: 'Switch',
  field: 'status',
  label: '状态',
  options: [
    { label: '停用', value: 0 }, // 第一项:默认作为未选中状态的标签和值
    { label: '启用', value: 1 }, // 第二项:默认作为选中状态的标签和值
  ],
  // options 已同时定义开关文案、绑定值和只读显示,无需再配置:
  // valueLabels: ['停用', '启用'],
  // attrs: { checkedChildren: '启用', unCheckedChildren: '停用' },
}

配置 options 时,组件直接使用第一项作为未选中状态、第二项作为选中状态,同时取得各自的 labelvalue。因此通常只写 options 即可,不要重复配置 valueLabelscheckedChildrenunCheckedChildren 或默认值为 falsefirstIsChecked

只有业务明确要求“第一项表示选中”时才反转顺序:

ts
{
  type: 'Switch',
  field: 'status',
  label: '状态',
  options: [
    { label: '启用', value: 1 }, // firstIsChecked 为 true 后,第一项表示选中
    { label: '停用', value: 0 }, // 第二项表示未选中
  ],
  attrs: {
    firstIsChecked: true,
  },
}

未配置 options 时,Switch 默认使用 true/false;配置 valueToNumber: true 后改用 1/0。此时可用 valueLabels 补充只读文案,或通过 Ant Design Vue 的 checkedChildrenunCheckedChildren 自定义开关内部内容。

TagSelect

TagSelect 把少量选项直接展示为可点击 Tag:

ts
{
  type: 'TagSelect',
  field: 'topics',
  label: '主题',
  options: topicOptions,
  attrs: {
    multiple: true,
    stringifyValue: false,
    placeholder: '暂无可选主题',
  },
}
配置字段值
默认单个 value
attrs.multiple: truevalue 数组
attrs.stringifyValue: true逗号字符串

顶层 ExtSelect 的 optionsdictNamevalueToNumberlabelAsValuestringifyValue 也可使用。组件事件包括 onCheck(effectData, tag, checked)onChange(effectData, tag, nextSelected)

tagViewer 只读配置

ts
// 关闭 Tag,显示普通文本
tagViewer: false

// 按值映射颜色
tagViewer: { enabled: 'green', disabled: 'default' }

// 颜色数组,按选项顺序循环
tagViewer: ['blue', 'green', 'orange']

// 完整条目
tagViewer: [
  { value: 1, label: '启用', color: 'green', icon: () => h(CheckOutlined) },
]

// 动态规则:函数参数是当前值
tagViewer: (value) => ({
  label: value ? '启用' : '停用',
  color: value ? 'green' : 'red',
})

配置 options 后默认开启 Tag。全局颜色策略见字典与权限

完整可运行代码见选择输入示例

基于 MIT 许可发布