问题场景: 一个新增页面:(基础信息表单,一个数据列表的表单),数据列表里面的表单数是动态添加的。数据结构大概是这样:
const params = {
userInfo: {
name: 'tom',
address: '*****',
},
members: [
{
relationship: '1',
name: 'tony',
phones: [
{
···
}
]
},
{
relationship: '2',
····
},
]
}
这个members是动态添加的表单,name为必填项需要做校验。
最开始的思路是定义一个form的列表,加一个member就往里面添加一个表单对象。提交时循环form列表用validate()进行校验,但是会出现一个问题就是添加的表单对象并没有绑定dom。
<template>
<div>···</div>
<div v-for="(item, index) in state.memberInfo" :key="index">
<el-form
:model="state.memberInfo[index].form"
:ref="`form${index}`"
>
····
</el-form>
</div>
<div @click="handleAddItemClick">添加Member</div>
</template>
<script setup>
import { reactive } from 'vue'
const state = reactive({
form0: null, // 默认有一个,可以继续新增
memberInfo: [
{
form: {....},
...
}
]
})
// 添加一个表单到列表
const handleAddItemClick = () => {
// 这里新定义的form1 或者form2是获取不到绑定的ref
state[`form${state.memberInfo.length}`] = null
state.memberInfo.push({...})
}
// 提交表单
const submit = () => {
try {
// 因为动态添加的form是没有绑定上ref的,这里会报错
const validList = state.memberInfo.map((item,index)=> {
return state[`form${index}`].validForm()
})
Promise.all(validList).then(res => {
···
}).catch(err => {
···
})
}.catch( err => {
···
})
}
</script>
翻了一下文档发现ref 可以接收一个函数值,用于对存储引用位置的完全控制。
<el-form
// 这样能成功获取到节点
:ref="el => state[`form${index}`] = el"
>
最后还有一种最简单的方法,直接写固定的ref。不管用多少次都可以获取到所有绑定的节点。
<el-form
ref="formList"
>
<script setup>
import { ref } from 'vue'
// formList会存储所有ref为'formList'的实例
const formList = ref(null)
有其他更好的方法可以指导一下,一起学习一起进步~