88 lines
5.0 KiB
JSON
88 lines
5.0 KiB
JSON
{
|
||
"slug": "formmodal",
|
||
"end": "react",
|
||
"curated": true,
|
||
"summary": "React 端表单弹窗:visible 控制挂载,fields 描述字段,组件内校验后经 onSubmit 回传整份表单对象。",
|
||
"usage": [
|
||
"受控开关:visible 为假时组件直接 return null 不渲染任何 DOM,为真才生成遮罩层(FormModal.jsx:10,18)。",
|
||
"字段由数据描述:fields=[{ key, label, required, placeholder }],未传时用组件内 DEFAULT_FIELDS(姓名、邮箱必填,角色选填)三条(FormModal.jsx:4-8,10)。",
|
||
"内部把 value 复制进 useState 的 form,visible 变真时用 useEffect 重置 form 与 errors,所以每次打开都是干净状态(FormModal.jsx:11-16)。",
|
||
"提交逻辑在组件内:遍历 fields 做必填与邮箱正则校验,errors 非空则 setErrors 后 return(不关闭),通过则 onSubmit({ ...form }) 并紧接着 onCancel()(FormModal.jsx:24-34)。",
|
||
"输入用受控写法:value={form[f.key] || ''} 加 onChange 调 onInput(key, e),修改任一字段时会同时删掉该字段的已有错误(FormModal.jsx:20-23,50-55)。",
|
||
"遮罩点击关闭只在点到遮罩自身时触发:onClick 里判断 e.target === e.currentTarget 才调 onCancel,点弹窗体内部不会误关(FormModal.jsx:37)。"
|
||
],
|
||
"bestPractices": [
|
||
"提交成功后组件会自己调 onCancel,父组件只需在 onSubmit 里处理数据,不必再手动关一次(否则会重复触发关闭逻辑)(FormModal.jsx:32-33)。",
|
||
"value 只在 visible 变真时同步进内部状态,弹窗打开期间改 value 不会反映到表单上;编辑场景请先更新 value 再打开(FormModal.jsx:14-16)。",
|
||
"邮箱格式校验写死了 key === 'email',字段表里换个 key(如 contactEmail)就不再校验格式,只做必填(FormModal.jsx:29)。",
|
||
"fields 的 placeholder 会原样透传到 input,label 与必填星号由组件根据 required 自动渲染,不要在 label 里写「*」(FormModal.jsx:46-53)。"
|
||
],
|
||
"apiCarrier": {
|
||
"kind": "props",
|
||
"note": "React 端 API 由四个 props 与两个回调组成:visible 决定挂载、title 与 fields 决定内容、value 提供初始表单数据,onSubmit 回传校验通过的表单对象、onCancel 通知关闭;组件不暴露 ref,也没有插槽。",
|
||
"table": [
|
||
{
|
||
"name": "visible",
|
||
"type": "boolean,默认 false",
|
||
"desc": "弹窗可见性;为假时不渲染 DOM,为真时触发一次状态重置"
|
||
},
|
||
{
|
||
"name": "title",
|
||
"type": "string,默认 '表单'",
|
||
"desc": "弹窗标题栏文案"
|
||
},
|
||
{
|
||
"name": "fields",
|
||
"type": "Array<{ key, label, required, placeholder }>",
|
||
"desc": "字段定义,逐项渲染 .kole-form-row;缺省用内置三条默认字段"
|
||
},
|
||
{
|
||
"name": "value",
|
||
"type": "object,默认 {}",
|
||
"desc": "表单初始值,key 与 fields 的 key 对应;打开时同步进内部状态"
|
||
},
|
||
{
|
||
"name": "onSubmit",
|
||
"type": "(form) => void",
|
||
"desc": "校验通过后调用,载荷是内部表单对象的浅拷贝"
|
||
},
|
||
{
|
||
"name": "onCancel",
|
||
"type": "() => void",
|
||
"desc": "取消、关闭、遮罩点击与提交成功四条路径都调用它"
|
||
}
|
||
]
|
||
},
|
||
"a11y": [
|
||
"遮罩与弹窗体都没有 role=\"dialog\" / aria-modal=\"true\",读屏器不会把它识别为对话框(FormModal.jsx:37-38)。",
|
||
"打开弹窗时没有把焦点移进弹窗,关闭后也没有归还给触发按钮;键盘用户需要自己 Tab 过去(FormModal.jsx:18-36)。",
|
||
"<label> 没有 htmlFor 与 input 的 id 关联(组件未生成 id),点击标签文字不会聚焦输入框(FormModal.jsx:46-53)。",
|
||
"错误信息未用 aria-invalid 或 aria-describedby 关联到输入框,读屏器无法在聚焦时读出「邮箱格式不正确」(FormModal.jsx:51,56)。"
|
||
],
|
||
"resources": [
|
||
{
|
||
"file": "frameworks/FormModal.jsx",
|
||
"kind": "React 组件",
|
||
"desc": "FormModal.jsx —— React 实现:DEFAULT_FIELDS、受控输入、组件内校验与两条回调"
|
||
},
|
||
{
|
||
"file": "frameworks/FormModal.css",
|
||
"kind": "样式文件",
|
||
"desc": "FormModal.css —— 组件 import 的弹层分区样式与 .is-error 错误态"
|
||
}
|
||
],
|
||
"exampleIds": [
|
||
"formmodal-ex-1"
|
||
],
|
||
"notes": [
|
||
"props 解构与默认值:frameworks/FormModal.jsx:10",
|
||
"默认字段表:frameworks/FormModal.jsx:4-8",
|
||
"打开时重置:frameworks/FormModal.jsx:14-16",
|
||
"提交校验与回传:frameworks/FormModal.jsx:24-34",
|
||
"受控输入与错误清除:frameworks/FormModal.jsx:20-23,52-54",
|
||
"遮罩自身点击判断:frameworks/FormModal.jsx:37",
|
||
"consumedApi.emits 里的 onChange/onInput/onClick 都是绑在内部 input、遮罩与按钮上的处理器,不是对外 props,未进 table。",
|
||
"契约 dims 的 columns=one/two 在 JSX 里没有多列实现,state 也没有 loading 分支,按实现写。"
|
||
]
|
||
}
|