标签页控件封装核心是实现各页独立状态管理与表单控制。需用 reactive 数组+唯一 key 管理每页 name、label、formdata、rules;每页配独立 el-form 实例并动态 ref 绑定;提交前逐页校验,失败则跳转并定位错误;组件通过 props/emits 对接外部,支持插槽与最小页数限制。

明确封装目标:标签页控件不是单纯增删 DOM
封装的重点不是“加几个 tab 标签”,而是让每个标签页具备独立状态、可校验、可提交、可回显,并且新增/删除行为不影响其他页的数据完整性。Element Plus 的 el-tabs 本身不管理表单逻辑,所以必须把表单字段、验证规则、提交动作都纳入组件内部统一控制。
结构设计:用 reactive 数组 + 唯一 key 管理标签页
每个标签页应是一个独立对象,包含:name(唯一标识)、label(显示名)、formData(该页表单数据)、rules(校验规则)。不建议用 index 作为 key,改用 Date.now() + Math.random() 或 cuid() 生成稳定唯一 ID。
- 初始化时至少保留一个默认标签页,避免空数组导致 v-for 报错
- 新增时 push 新对象,同时用
nextTick聚焦到新页第一个输入框(如需) - 删除时先校验当前页是否已修改,可弹窗提示“未保存内容将丢失”
表单校验:每个标签页配独立 el-form 实例
不能共用一个 ref="formRef",否则 validate() 会混掉所有页的字段。正确做法是为每个标签页维护一个 formRefs: Ref<record forminstance>></record>,key 对应 tab 的 name,动态绑定 :ref="el => formRefs.value[item.name] = el"。
- 提交前遍历所有 tab,逐个调用
formRefs.value[name]?.validate() - 任一 tab 校验失败,就
el-tabs切换到对应页并滚动到首个错误字段 - 编辑态回显时,直接将后端返回的各页数据按 name 映射赋值给对应
formData
封装成可复用组件:接收 props + 暴露事件
组件对外只暴露必要接口:通过 props 接收初始 tabs 配置(含默认字段和规则),通过 emits 触发 update:modelValue(同步全部页数据)、submit(所有页校验通过后触发)、tab-change(切换页时通知父组件)。
- 内部不用
v-model绑定整个数组,而是用computed({ get, set })包装 modelValue,保证响应式更新穿透 - 支持插槽:例如
#tab-label="{ item }"自定义 tab 标题,#tab-content="{ item, formRef }"自定义表单内容 - 禁用删除最后一项,或允许但要求至少保留一页(由 prop
minTabs控制)
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











