1. Demand scenario:
There is the following usage scenario, the name 111, name 222, and name 333 are placed in a large array, and then displayed through the first layer of for loop. The name 333 array contains its own sub-array, and the sub-array is displayed through the second for loop. When we choose the distribution method, those that meet the selection criteria will only display the first-time ratio corresponding to that row. Finally, form validation is performed on each item in the sub-array.
Regarding the array structure, we can customize it on the front end.
const form = reactive({
title: '',
templateList: [{
key: 'region',
label: '名称111',
list: [{
settlement_type: '1', limit_days: '0', rate: '', settlement_way: '' }]
}, {
key: 'partner',
label: '名称222',
list: [{
settlement_type: '2', limit_days: '0', rate: '', settlement_way: '' }]
}, {
key: 'user',
label: '名称333',
list: [
{
settlement_type: '3', limit_days: '30', rate: '', settlement_way: '' },
{
settlement_type: '3', limit_days: '60', rate: '', settlement_way: '' },
{
settlement_type: '3', limit_days: '180', rate: '', settlement_way: '' },
{
settlement_type: '3', limit_days: '90', rate: '', settlement_way: '' },
]
}]
})
2. Solution:
You can consider using to v-for
perform double-layer nested loops, and there are several points to note:
1. The index in the parent loop must be distinguished from the index in the sub-loop when writing, so as not to confuse them.
2. Do not omit the :key value. The parent loop corresponds to the index of the parent, and the child loop corresponds to the index of the child.
3. Code implementation:
<template>
<!-- ========= 这是循环取出第一层数组,保存在item里面 ======== -->
<div
v-for="(item,index) in form.templateList"
:key="index"
>
<div style="margin-bottom:10px;">
{
{ item.label }}
</div>
<!-- ========= 这是循环出第二层数组,注意要在item里面取出 ======== -->
<a-row
:gutter="15"
v-for="(itemChild,indexChild) in item.list"
:key="indexChild"
>
<a-col :span="8">
<a-form-item
:field="`templateList[${index}].list[${indexChild}].rate`"
:label="Number(itemChild.limit_days) > 0 ? itemChild.limit_days + '天利息':'利息'"
:rules="formRules.rate"
>
<a-input
v-model="itemChild.rate"
placeholder="请填写"
allow-clear
>
<template #append>
%
</template>
</a-input>
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item
:field="`templateList[${index}].list[${indexChild}].settlement_way`"
label="发放方式"
:rules="formRules.settlement_way"
>
<a-select
v-model="itemChild.settlement_way"
placeholder="请选择"
allow-clear
@change="((val) => {
changeSelect(val,itemChild)
})"
>
<a-option
v-for="item in giveModelList"
:key="item.key"
:label="item.val"
:value="item.key"
/>
</a-select>
</a-form-item>
</a-col>
<a-col
:span="8"
v-if="itemChild.settlement_way === '3'"
>
<a-form-item
:field="`templateList[${index}].list[${indexChild}].first_rate`"
label="首发比例"
:rules="formRules.first_rate"
>
<a-input
v-model="itemChild.first_rate"
placeholder="请填写"
allow-clear
>
<template #append>
%
</template>
</a-input>
</a-form-item>
</a-col>
</a-row>
</div>
</template>
<script setup lang="ts">
import {
ref, unref, reactive, onMounted } from "vue"
const form = reactive({
title: '',
templateList: [{
key: 'region',
label: '名称111',
list: [{
settlement_type: '1', limit_days: '0', rate: '', settlement_way: '' }]
}, {
key: 'partner',
label: '名称222',
list: [{
settlement_type: '2', limit_days: '0', rate: '', settlement_way: '' }]
}, {
key: 'user',
label: '名称333',
list: [
{
settlement_type: '3', limit_days: '30', rate: '', settlement_way: '' },
{
settlement_type: '3', limit_days: '60', rate: '', settlement_way: '' },
{
settlement_type: '3', limit_days: '180', rate: '', settlement_way: '' },
{
settlement_type: '3', limit_days: '90', rate: '', settlement_way: '' },
]
}]
})
const formRules = {
rate: [{
required: true, validator: validatePercentageNumber, trigger: 'blur' }],
settlement_way: [{
required: true, trigger: 'change', message: '请选择' }],
first_rate: [{
required: true, validator: validatePercentageNumber, trigger: 'blur' }]
}
const giveModelList = [
{
key: '1', val: '一次性发放' },
{
key: '2', val: '每天发放' },
{
key: '3', val: '首次+每天' }
]
</script>
<style lang="less" scoped></style>
plan 1:
This method is the simplest, by directly judging settlement_way
whether the word of the sub-array is equal to '3'
v-if="itemChild.settlement_way === '3'"
Scenario 2:
At first, I didn't expect to use settlement_way
whether the field is equal to '3', which can be solved directly. Another method is used, and it is also recorded that this method is often used.
- Create a new array, and if it meets the judgment conditions, use
父级index和子级index
to assemble it字符串
, and then push it into the new array;- If the judgment condition is not met, for loop the new array, if there is a certain value in the currently
父级index和子级index
assembled string array, delete the value from the array.等于
- In html,
v-if
it is judged whether (includes
) contains the value in the array, and if so, it will directly display the first rate input, otherwise it will be hidden.
<a-col :span="8">
<a-form-item
:field="`templateList[${index}].list[${indexChild}].settlement_way`"
label="发放方式"
:rules="formRules.settlement_way"
>
<a-select
v-model="itemChild.settlement_way"
placeholder="请选择"
allow-clear
@change="((val) => {
changeSelect(val,index,indexChild,itemChild)
})"
>
<a-option
v-for="item in giveModelList"
:key="item.key"
:label="item.val"
:value="item.key"
/>
</a-select>
</a-form-item>
</a-col>
<a-col
:span="8"
v-if="indexArr.length > 0 && indexArr.includes(`${index}${indexChild}`)"
>
<a-form-item
:field="`templateList[${index}].list[${indexChild}].first_rate`"
label="首发比例"
:rules="formRules.first_rate"
>
<a-input
v-model="itemChild.first_rate"
placeholder="请填写"
allow-clear
>
<template #append>
%
</template>
</a-input>
</a-form-item>
</a-col>
const indexArr = ref([])
function changeSelect(val:any, index:any, indexChild:any, itemChild:any) {
if (val == '3') {
indexArr.value.push(`${
index}${
indexChild}`)
} else {
for (let i = 0; i < indexArr.value.length; i++) {
if (`${
index}${
indexChild}` == indexArr.value[i]) {
indexArr.value.splice(i, 1)
}
}
delete itemChild.first_rate
}
console.log(indexArr.value, 'indexArr') // ['00','10','21','22','23']
}
Print result:
4. Form validation for arrays of complex objects
Because all items are required, it involves the verification of each item in the sub-array. Validation needs to be added to each element.
Take a look at the effect diagram of this verification first.
Known data structures:
const form = reactive({
title: '',
templateList: [{
key: 'region',
label: '名称111',
list: [{
settlement_type: '1', limit_days: '0', rate: '', settlement_way: '' }]
}, {
key: 'partner',
label: '名称222',
list: [{
settlement_type: '2', limit_days: '0', rate: '', settlement_way: '' }]
}, {
key: 'user',
label: '名称333',
list: [
{
settlement_type: '3', limit_days: '30', rate: '', settlement_way: '' },
{
settlement_type: '3', limit_days: '60', rate: '', settlement_way: '' },
{
settlement_type: '3', limit_days: '180', rate: '', settlement_way: '' },
{
settlement_type: '3', limit_days: '90', rate: '', settlement_way: '' },
]
}]
})
const formRules = {
rate: [{
required: true, validator: validatePercentageNumber, trigger: 'blur' }],
settlement_way: [{
required: true, trigger: 'change', message: '请选择' }],
first_rate: [{
required: true, validator: validatePercentageNumber, trigger: 'blur' }]
}
After defining the verification rules, you only need to set :field
the path in the data object. :field=" templateList[${index}].list[${indexChild}].rate
"
<div
class="outline"
v-for="(item,index) in form.templateList"
:key="index"
>
<div style="margin-bottom:10px;">
{
{ item.label }}
</div>
<a-row
:gutter="15"
v-for="(itemChild,indexChild) in item.list"
:key="indexChild"
>
<a-col :span="8">
<a-form-item
:field="`templateList[${index}].list[${indexChild}].rate`"
:label="Number(itemChild.limit_days) > 0 ? itemChild.limit_days + '天利息':'利息'"
:rules="formRules.rate"
>
<a-input
v-model="itemChild.rate"
placeholder="请填写"
allow-clear
>
<template #append>
%
</template>
</a-input>
</a-form-item>
</a-col>