VUE3和antd组件库实现动态展示tab页,并且每个tab页签下动态生成form表单。

文章讲述了如何在Vue应用中,根据后端返回数据动态生成标签页组件,每个标签对应一个表单进行数据输入。重点介绍了如何使用ref和动态校验表单以确保数据的正确性。
摘要由CSDN通过智能技术生成

需求:
根据后端返回数据使用标签页组件动态生成标签,每个标签展示对应标签的form表单。提交时需要动态校验表单。

  <a-tabs v-model:activeKey="stateK.activeTab">
                    <a-tab-pane v-for="(tab, index) in stateK.editNameModel" :key="tab.id" :tab="tab.name">
                        <div class="edit-form">
                            <a-form :model="tab.data" :ref="getFormRef(index)">
                                <a-row v-for="(item, index) in tab.data" :key="index" :gutter="24">
                                    <a-col :span="10">
                                        <a-form-item
                                            label="项目全称"
                                            :rules="[{ required: true, message: '请输入项目全称!', trigger: 'blur' }]"
                                            :name="[index, 'projectName']"
                                        >
                                            <a-input v-model:value="item.projectName" disabled />
                                        </a-form-item>
                                    </a-col>
                                    <a-col :span="6">
                                        <a-form-item
                                            label="项目序号"
                                            :rules="[{ required: true, message: '请输入项目序号!', trigger: 'blur' }]"
                                            :name="[index, 'projectSeqNo']"
                                        >
                                            <a-input-number
                                                style="width: 100%"
                                                :maxlength="7"
                                                show-count
                                                v-model:value="item.projectSeqNo"
                                            />
                                        </a-form-item>
                                    </a-col>
                                    <a-col :span="8">
                                        <a-form-item
                                            label="项目简称"
                                            :rules="{ required: true, validator: validateShortName, trigger: 'blur' }"
                                            :name="[index, 'projectShortName']"
                                        >
                                            <a-input v-model:value="item.projectShortName" :maxlength="7" show-count />
                                        </a-form-item>
                                    </a-col>
                                </a-row>
                            </a-form>
                        </div>
                    </a-tab-pane>
                </a-tabs>
const stateK = reactive({
 editNameModel: []
})
//声明表单ref动态生成具体数量不知道,所以是数组
 const editNameRef = ref([])
 //getFormRef 在 Vue 中,使用 ref 创建的引用变量是响应式的。在组件渲染期间,如果你修改了 editNameRef,那么 Vue 会在下一个渲染周期中重新渲染组件并更新相关的 DOM。
 //但是,editNameRef 在模板中使用的时候,可能是在组件渲染之前被访问到,导致它是空的。这是因为在模板中的代码(如 @click="submitForm")可能在组件初始化之前就被解析。
 //为了解决这个问题,你可以使用 ref 创建一个响应式的数组,然后在 setup 钩子中根据表单的数量动态地填充这个数组。
 //这里困扰我一下午!!!!!
  const getFormRef = index => {
        editNameRef.value[index] = editNameRef.value[index] || ref(null)
        return editNameRef.value[index]
    }
//获取动态数据
  function handleGetName() {
        post('xxx').then(data => {
            if (data.code === 200) {
                stateK.editNameVisible = true
                stateK.editNameModel = data.data
                stateK.activeTab = stateK.editNameModel[0].id
            } else {
                message.error(data.message || '获取项目简称失败')
            }
        })
    }
    //保存校验
       function handleChangeName() {
        let formData = []
        Promise.all(editNameRef.value.map(formRef => formRef.value[0].validate()))
            .then(() => {
                stateK.editNameModel.forEach(tab => {
                    tab.data.forEach(item => {
                        formData.push({
                            mappingId: item.mappingId,
                            projectId: item.projectId,
                            projectName: item.projectName,
                            projectSeqNo: item.projectSeqNo,
                            projectShortName: item.projectShortName,
                            templateId: item.templateId
                        })
                    })
                })
                put('xxxx', formData).then(data => {
                    if (data.code === 200) {
                        message.success('操作成功')
                        stateK.editNameVisible = false
                        getTableList()
                    } else {
                        message.error(data.message || '修改项目简称失败')
                    }
                })
            })
            .catch(e => {
                let errMsg = findObjectIndex(stateK.editNameModel, e.values[0])
                if (errMsg) {
                    message.info(`请检查-${errMsg.name}-模板下的第-${errMsg.index + 1}-条数据`)
                } else {
                    message.info('请检查数据是否填写完整')
                }
            })
    }
    //由于是tab页签,用户有可能改了其他页签的数据之后切换了页签,导致校验不通过时会不知道,所以做了一个提示,用出错的数据去原数据中去寻找给出提示
    function findObjectIndex(dataList, targetObject) {
        // 遍历大数组
        for (const item of dataList) {
            // 在当前对象的data数组中查找目标对象
            const index = item.data.findIndex(obj => {
                // 检查mappingId是否匹配
                return obj.projectName === targetObject.projectName
            })
            // 如果找到目标对象,则返回其所在的大数组对象的id和在data数组中的索引
            if (index !== -1) {
                return { ...item, index: index }
            }
        }
        // 如果未找到目标对象,返回 null
        return null
    }

效果如下
在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

屎山制造者2022

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值