87 lines
4.9 KiB
JSON
87 lines
4.9 KiB
JSON
{
|
||
"slug": "formmodal",
|
||
"end": "vue2",
|
||
"curated": true,
|
||
"summary": "Vue 2 端表单弹窗:v-if=\"visible\" 控制显隐,fields 与 value 描述表单,提交校验后 emit submit 与 cancel。",
|
||
"usage": [
|
||
"显隐是 v-if 而不是加类:<div class=\"kole-formmodal-mask\" v-if=\"visible\">,关掉 visible 整棵弹窗子树会被销毁(FormModal.vue2.vue:2)。",
|
||
"用法写 :visible=\"visible\" 加 @cancel=\"close\",本端没有 update:visible,不能用 .sync 或 v-model 直接双向绑定可见性(FormModal.vue2.vue:33;示例 formmodal-ex-1)。",
|
||
"字段定义传 :fields,每项 { key, label, required, placeholder };未传时 default 工厂返回与演示页一致的三条字段(FormModal.vue2.vue:35-42)。",
|
||
"内部表单是 data.form(Object.assign 复制 value)与 data.errors 两个对象,watch visible 为真时重置两者,实现每次打开都是干净状态(FormModal.vue2.vue:46-50)。",
|
||
"输入用 :value 加 @input 手写回写(onInput(key, $event)),数据不落在字段上,改字段时用 $set / $delete 保证响应式(FormModal.vue2.vue:11-17,52-55)。",
|
||
"校验在 submit 方法内:必填与邮箱正则逐项判断,errors 非空就 this.errors = errors 并 return;通过则先 $emit('submit', 拷贝的表单) 再 $emit('cancel')(FormModal.vue2.vue:56-66)。"
|
||
],
|
||
"bestPractices": [
|
||
"提交成功会连发 submit 与 cancel 两个事件,父组件只接 @submit 时弹窗也会收到 cancel;若 close 里做了「放弃填写」的埋点需要区分来源(FormModal.vue2.vue:64-65)。",
|
||
"props.value 只在 visible 变真时同步进 form,弹窗打开期间改 value 不会回灌到输入框;编辑场景要先改 value 再置 visible(FormModal.vue2.vue:49)。",
|
||
"遮罩关闭用的是 @click.self(只在点到遮罩自身时派发 cancel),所以模板里不需要额外的 target 判断(FormModal.vue2.vue:2)。",
|
||
"value 是 Object 类型,default 必须写成函数(default: () => ({})),否则所有实例会共享同一个对象(FormModal.vue2.vue:43)。"
|
||
],
|
||
"apiCarrier": {
|
||
"kind": "props",
|
||
"note": "Vue 2 端 API 载体是 props 加 emit:visible/title/fields/value 四项 props 描述弹窗,submit(带表单对象)与 cancel(无载荷)两个事件把结果交给父组件;组件没有插槽与 ref 句柄,也没有 update:visible 之类的回写事件。",
|
||
"table": [
|
||
{
|
||
"name": "visible",
|
||
"type": "Boolean,默认 false",
|
||
"desc": "显隐开关,为假时整棵弹窗子树被 v-if 销毁"
|
||
},
|
||
{
|
||
"name": "title",
|
||
"type": "String,默认 '表单'",
|
||
"desc": "标题栏文案"
|
||
},
|
||
{
|
||
"name": "fields",
|
||
"type": "Array,默认三条内置字段",
|
||
"desc": "字段定义数组,每项含 key/label/required/placeholder"
|
||
},
|
||
{
|
||
"name": "value",
|
||
"type": "Object,默认工厂返回 {}",
|
||
"desc": "表单初始值,打开时浅拷贝进内部 form"
|
||
},
|
||
{
|
||
"name": "submit",
|
||
"type": "事件,载荷为表单对象拷贝",
|
||
"desc": "校验通过后派发,随后立刻派发 cancel"
|
||
},
|
||
{
|
||
"name": "cancel",
|
||
"type": "事件,无载荷",
|
||
"desc": "×、取消按钮、遮罩点击与提交成功四条路径都会派发"
|
||
}
|
||
]
|
||
},
|
||
"a11y": [
|
||
"弹层没有 role=\"dialog\" 与 aria-modal,读屏器不会识别为对话框(FormModal.vue2.vue:2-3)。",
|
||
"打开后焦点不进入弹窗,关闭(v-if 销毁)后也不会自动归还焦点,键盘用户需自行导航(FormModal.vue2.vue:2)。",
|
||
"标签用 <label> 但未与输入框做 for/id 关联,点击文字不聚焦(FormModal.vue2.vue:10-17)。",
|
||
"错误提示 .kole-form-err 只是视觉文本,没有 aria-invalid 或 describedby 关系,辅助技术读不到校验结果(FormModal.vue2.vue:13,18)。"
|
||
],
|
||
"resources": [
|
||
{
|
||
"file": "frameworks/FormModal.vue2.vue",
|
||
"kind": "Vue 2 组件实现(Options API 单文件组件)",
|
||
"desc": "FormModal.vue2.vue —— 模板、四个 prop、visible watcher 与 submit 校验方法"
|
||
},
|
||
{
|
||
"file": "frameworks/FormModal.css",
|
||
"kind": "样式文件",
|
||
"desc": "FormModal.css —— <style src> 引入的弹层分区与表单错误态样式"
|
||
}
|
||
],
|
||
"exampleIds": [
|
||
"formmodal-ex-1"
|
||
],
|
||
"notes": [
|
||
"prop 声明与默认值:frameworks/FormModal.vue2.vue:32-44",
|
||
"data 与 visible watcher 重置:frameworks/FormModal.vue2.vue:46-50",
|
||
"输入回写(含 $set / $delete):frameworks/FormModal.vue2.vue:52-55",
|
||
"submit 校验与双事件:frameworks/FormModal.vue2.vue:56-66",
|
||
"遮罩自身点击:frameworks/FormModal.vue2.vue:2",
|
||
"样式引入:frameworks/FormModal.vue2.vue:71",
|
||
"契约 dims 的 columns=one/two 与 loading 状态在本端模板里都没有实现,按实现写。"
|
||
]
|
||
}
|