{ "schemaVersion": 1, "sourceKind": "authored-spec", "provenance": "authored-in-repo", "specFile": "spec/移动端规格.md", "specSection": "43 · 选择器 Picker", "confidence": "high", "slug": "mobile-picker", "name": "选择器 Picker", "semanticTypeCandidates": [ "picker", "select", "wheel" ], "variantDimensions": [ { "name": "mode", "values": [ "single", "multiple" ] }, { "name": "round", "values": [ "false", "true" ] } ], "representativeVariants": [ { "mode": "single", "round": "true", "label": "单列滚轮(城市这类单值选择)" }, { "mode": "multiple", "round": "true", "label": "多列滚轮(时 / 分两列各选一项)" }, { "mode": "single", "round": "false", "label": "直角(不含圆角)" }, { "mode": "single", "round": "true", "label": "禁用(整块置灰且不响应)" } ], "anatomy": { "mask": "遮罩,点击关闭(closeOnMask=false 时不关)", "picker": "底部浮层面板,role=dialog + aria-modal", "picker__header": "取消 / 标题 / 确定三格,标题元素由 aria-labelledby 指向", "picker__columns": "列容器,single 一列、multiple 多列等分", "picker__column": "单列,role=listbox + aria-label 说明这列在选什么,可滚动", "picker__option": "单个选项,role=option + aria-selected,行高不小于 44px" }, "structurePatterns": { "mode": "single(单列滚轮)/ multiple(多列滚轮,各列独立选中)", "round": "false(直角)/ true(靠内容一侧切圆角)", "disabled": "false(可选)/ true(整块置灰且不响应)" }, "usageHints": [ "从一组有限且已知的选项里选出一项或几项(城市、分值、时间),是表单里下拉框在触屏上的形态", "可绑定到 Popup 的底部形态,但本组件自带遮罩与面板,不要在弹出层里再套一层", "遮罩点击关闭;closeOnMask=false 时不关闭", "选项行高不小于 44px,滚动容器 -webkit-overflow-scrolling: touch", "点击选项只改本列高亮,不改宿主的值;确认时才提交", "确定 / 取消按钮热区不小于 44px", "取消即返回:点取消或遮罩丢弃本次点选,宿主侧的值回到打开前的状态" ], "doNotInvent": [ "选项数据源与联动规则(由宿主传入 columns,本组件不发明城市库或级联关系)", "滚轮惯性 / 吸附动画的物理参数", "搜索过滤与键盘输入定位(那是 Input / Search 的职责)", "多选(一次选多个值)——本组件是「多列各选一项」,不是「一列选多项」" ], "unknowns": [ "面板最大高度是否应随列数增长(当前固定 max-height 一列 200px)", "是否要支持「不选」的空值项", "列数上限(当前实现不限制,但三列以上在 375px 宽度下每列会很窄)" ], "interaction": [ "遮罩点击关闭;closeOnMask=false 时不关闭", "选项行高不小于 44px,滚动容器 -webkit-overflow-scrolling: touch", "点击选项只改本列高亮(同列其余项取消高亮),不改宿主的值;确认时才提交", "确定 / 取消按钮热区不小于 44px", "取消防返回:点取消或遮罩丢弃本次点选,宿主侧的值回到打开前的状态" ], "accessibility": [ "浮层 role=\"dialog\" + aria-modal=\"true\",标题元素 id 由 aria-labelledby 指向", "每列 role=\"listbox\" + aria-label,选项 role=\"option\" + aria-selected", "遮罩 aria-hidden=\"true\"(纯装饰,读屏不播报)", "选中值以文本呈现在标题里(不依赖视觉滚动位置),收起态写 aria-hidden=\"true\"", "禁用项写 aria-disabled=\"true\",读屏播报不可用" ], "api": { "source": "implementation", "note": "props / events / slots 为 6 端实现的公共接口(说明文字取自规格对应小节)。字段名与各端源码逐名核对:node tools/verify-mobile-docs.mjs", "requiredNote": "「必传」按严格定义:实现里**没有默认值**时才为 Y(本门禁逐条核对 props 与各端源码的默认值,防止契约与实现脱节)。", "props": [ { "name": "mode", "type": "'single' | 'multiple'", "default": "'single'", "desc": "变体 mode:single 单列滚轮,multiple 多列滚轮(规格 §43.3)", "required": false }, { "name": "round", "type": "boolean", "default": "false", "desc": "变体 round:靠内容一侧是否切圆角(规格 §43.3)", "required": false }, { "name": "open", "type": "boolean", "default": "false", "desc": "状态 open:浮层是否展开(规格 §43.4)", "required": false }, { "name": "closeOnMask", "type": "boolean", "default": "true", "desc": "遮罩点击是否关闭(规格 §43.5)", "required": false }, { "name": "value", "type": "Array", "default": "[]", "desc": "当前选中值,按列顺序排列(单列时长度 1);用于让选中项可见(规格 §43.6)", "required": false }, { "name": "columns", "type": "Array<{ label: string, options: Array }>", "default": "[]", "desc": "列定义(宿主提供,本组件不发明选项数据源)(规格 §43.7)", "required": false }, { "name": "disabled", "type": "boolean", "default": "false", "desc": "变体 disabled:整块置灰且不响应(规格 §43.4)", "required": false }, { "name": "title", "type": "string", "default": "''", "desc": "面板标题(空串时用默认「选择」)(规格 §43.2 picker__header)", "required": false } ], "events": [ { "name": "confirm", "params": "value: Array", "desc": "点击确定时触发,回传各列当前选中值(规格 §43.5)" }, { "name": "close", "params": "—", "desc": "点击取消或遮罩(closeOnMask=true 时)时触发(规格 §43.5)" } ], "slots": [ { "name": "default", "desc": "自定义内容(追加在面板之前,常见用法是放触发器)" } ] }, "variantClasses": { "mode": { "single": [ ".kole-m-picker--single" ], "multiple": [ ".kole-m-picker--multiple" ] }, "round": { "false": [], "true": [ ".kole-m-picker--round" ] } }, "demos": [ { "id": "single", "group": "01 组件类型", "title": "单列滚轮", "desc": "mode=single:点选项即高亮,选中项用品牌色并与 aria-selected 同步,不依赖视觉位置。", "variant": "mode=single" }, { "id": "multiple", "group": "01 组件类型", "title": "多列滚轮", "desc": "mode=multiple:时 / 分两列各自独立选中,确认时一并回传。", "variant": "mode=multiple" }, { "id": "selected", "group": "02 组件状态", "title": "选中态与禁用项", "desc": "选中用 is-selected + aria-selected 双通道;禁用项置灰并写 aria-disabled,点击不响应。", "variant": "状态 selected | disabled" }, { "id": "closed", "group": "02 组件状态", "title": "收起态", "desc": "默认态:遮罩 pointer-events: none,点触发器才把浮层与遮罩一起拉开。", "variant": "状态 closed" } ], "related": [ { "slug": "mobile-popup", "why": "通用弹出层;本组件就是底部浮层形态,不要在弹出层里再套一层选择器" }, { "slug": "actionsheet", "why": "动作面板也是底部升起的选项列表,但面向「点一下即执行」,不区分确定 / 取消" }, { "slug": "mobile-datepicker", "why": "同样是底部滚轮,但选项是年月日这类有历法语义的日期时才用它" }, { "slug": "mobile-cascader", "why": "选项之间有层级联动(省 → 市 → 区)时用级联选择器,而不是自己拼多列" }, { "slug": "mobile-input", "why": "选项数量不定或需要用户自由输入时用它,不要用选择器硬塞长列表" } ] }