{ "schemaVersion": 1, "sourceKind": "authored-spec", "provenance": "authored-in-repo", "specFile": "spec/移动端规格.md", "specSection": "32 · 表单 Form", "confidence": "high", "slug": "mobile-form", "name": "表单 Form", "semanticTypeCandidates": [ "form", "form-item", "field-group" ], "variantDimensions": [ { "name": "labelPosition", "values": [ "top", "left" ] }, { "name": "borderless", "values": [ "false", "true" ] } ], "representativeVariants": [ { "labelPosition": "top", "borderless": "false", "label": "默认(置顶标签 + 字段间分隔线)" }, { "labelPosition": "left", "borderless": "false", "label": "左标签(定宽 72px 与控件同行)" }, { "labelPosition": "top", "borderless": "true", "label": "无分隔线(靠留白分组,嵌在卡片里)" } ], "anatomy": { "form": "根元素,包住全部字段与提交行", "item": "单个字段,一列一个,字段之间用 1px 分隔线划分", "label": "字段标签;required=true 时前面带一个错误色星号", "star": "必填星号,装饰性(aria-hidden),语义由控件的 aria-required 承担", "control": "字段控件(原生 input / textarea,或包一层的可点区域)", "errorText": "字段级错误提示,落在该字段控件下方" }, "structurePatterns": { "labelPosition": "top(标签在控件上方,默认)/ left(标签定宽 72px 与控件同行)", "borderless": "false(字段之间有分隔线)/ true(不画线,靠留白分组)" }, "usageHints": [ "把一组字段(标签 + 控件 + 错误提示)组织成一次可提交的操作(下单、开票、认证)", "移动端窄屏放不下左右两列时标签默认置顶,只有需要一组字段纵向对齐时才退回到定宽左标签", "每个字段的错误提示必须贴在它自己的控件下方 —— 触屏上用户看不到「页头汇总错误」", "控件高度不小于 44px;非输入型控件(选择器一类)整行都是热区", "失焦即校验(触屏上软键盘收起会触发 blur),提交时再全量校验一次" ], "doNotInvent": [ "字段内容的业务校验规则(正则、长度、合法性判断都在宿主,本组件只表达结构)", "提交请求、失败重试与「提交中」的按钮态", "字段的联动显隐与动态增删(由宿主决定渲染什么)", "页首错误汇总条(移动端用字段级提示,不做汇总)" ], "unknowns": [ "左标签模式下标签列宽是否随字号变化(当前固定 72px)", "提交行是否允许放两个并列动作(如「保存草稿 + 提交」)", "只读(readonly)字段是否需要独立的视觉层,还是复用 disabled" ], "interaction": [ "控件高度不小于 44px;非输入型控件(选择器一类)整行都是热区,按下反馈是整行背景变化", "错误提示出现在控件正下方,不挤占输入区,也不跨到标签列", "失焦即校验(触屏上软键盘收起会触发 blur),提交时再全量校验一次", "校验失败时不跳转、不滚动到页首,错误就落在出错的字段上", "提交成功后写 data-submitted=\"true\" 作为可断言的提交凭证;星号与错误色不单独承载语义" ], "accessibility": [ "标签用 aria-labelledby 关联到控件(标签不是占位符的替代品)", "必填用控件的 aria-required=\"true\" 与原生 required 双写;星号本身 aria-hidden", "错误文案用 aria-describedby 关联到控件,并带 role=\"alert\" 播报", "禁用态用原生 disabled,读屏会播报不可用且键盘会跳过" ], "api": { "source": "implementation", "note": "props / events / slots 为 6 端实现的公共接口(说明文字取自规格对应小节)。字段名与各端源码逐名核对:node tools/verify-mobile-docs.mjs", "requiredNote": "「必传」按严格定义:实现里**没有默认值**时才为 Y(本门禁逐条核对 props 与各端源码的默认值,防止契约与实现脱节)。", "props": [ { "name": "fields", "type": "Array", "default": "[]", "desc": "字段数组,每项 { name, label, value, type, required, error, hint, placeholder }(规格 §32.2)", "required": false }, { "name": "labelPosition", "type": "'top' | 'left'", "default": "'top'", "desc": "变体 labelPosition:标签置顶还是定宽在控件左侧(规格 §32.3)", "required": false }, { "name": "borderless", "type": "boolean", "default": "false", "desc": "变体 borderless:字段之间是否画 1px 分隔线(规格 §32.3)", "required": false }, { "name": "disabled", "type": "boolean", "default": "false", "desc": "状态 disabled:整表置灰且不可聚焦(规格 §32.4)", "required": false }, { "name": "submitText", "type": "string", "default": "'提交'", "desc": "提交行按钮文案;空字符串表示不渲染提交行(规格 §32.5)", "required": false } ], "events": [ { "name": "submit", "params": "(fields)", "desc": "提交时触发,回传字段数组供宿主校验与请求(规格 §32.5)" }, { "name": "change", "params": "(name, value)", "desc": "字段值变化时触发,回传字段名与当前值(规格 §32.5)" } ], "slots": [ { "name": "default", "desc": "提交行之前的自定义字段区(宿主插入自己的字段结构,规格 §32.2 item)" } ] }, "variantClasses": { "labelPosition": { "top": [], "left": [ ".kole-m-form--left" ] }, "borderless": { "false": [], "true": [ ".kole-m-form--borderless" ] } }, "demos": [ { "id": "basic", "group": "01 组件类型", "title": "可提交表单", "desc": "置顶标签 + 必填星号 + 提示行;点提交执行校验并写入 data-submitted。", "variant": "labelPosition=top" }, { "id": "left", "group": "01 组件类型", "title": "标签在左", "desc": "labelPosition=left:标签定宽 72px 与控件同行,适合一组纵向对齐的字段。", "variant": "labelPosition=left" }, { "id": "borderless", "group": "01 组件类型", "title": "无分隔线", "desc": "borderless=true:字段之间靠留白分组,嵌在卡片里时用。", "variant": "borderless=true" }, { "id": "error", "group": "02 组件状态", "title": "校验错误", "desc": "is-error + aria-invalid 双写;错误文案在控件下方,标签与星号同时变错误色。", "variant": "状态 error" }, { "id": "disabled", "group": "02 组件状态", "title": "整表禁用", "desc": "字段置灰且不可聚焦,提交按钮一并置灰;读屏会播报不可用。", "variant": "disabled=true" } ], "related": [ { "slug": "mobile-input", "why": "单个字段的输入框(高度、清除按钮、错误态)由 Input 负责;Form 只管字段的组织与提交" }, { "slug": "mobile-textarea", "why": "多行文本字段用 Textarea(计数、自动增高);Form 的 item 只是把它包进标签与错误提示里" }, { "slug": "mobile-button", "why": "表单外的独立动作(取消、暂存)用 Button;只有「提交本表单」才用 Form 内置的提交行" } ] }