当前位置:   article > 正文

vue中使用v-for实现两次嵌套循环,判断某子元素是否显示,进行复杂表单校验_vue 嵌套循环

vue 嵌套循环

一、需求场景:

有以下一个使用场景,名称111、名称222、名称333,是放在一个大数组里的,然后通过第一层for循环显示出来的。名称333数组里又包含自己的子数组,子数组再通过第二次for循环展示出来。当我们选择发放方式的时候,符合选择条件的只显示自己对应那一行的首发比例。最后对子数组里的每一项进行表单校验
在这里插入图片描述
关于数组结构,我们前端这边可以自定义写好。

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: '' },
    ]
  }]
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

二、解决方法:

可以考虑使用 v-for 进行双层嵌套循环,其中有几个需要注意的点:

1. 父循环中的 index 与子循环的 index 写的时候必须区分开,不要搞混。
2. 不要忽略 :key 值。父级循环对应父级的index,子级循环对应子级的index。

三、代码实现:

<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117

方案1:

这种方式最简单,通过直接判断子数组 settlement_way 字是否等于 ‘3’

   v-if="itemChild.settlement_way === '3'"
  • 1

方案2:

一开始没想到用 settlement_way 字段是否等于 ‘3’,能直接解决。使用了另外的方法,也记录下,这种方法也经常会用到。

  1. 新建一个数组,符合判断条件的,使用 父级index和子级index 组装成 字符串 ,然后push进新数组;
  2. 不符合判断条件的,for循环新数组,如果当前 父级index和子级index 组装成的 字符串 等于 数组里的某值,则从数组里删除该值。
  3. html中 v-if 判断数组中是否( includes )包含该值,有的话直接显示首发比例input,否则隐藏。
<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
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']
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

打印结果:

在这里插入图片描述

四、对复杂对象型数组进行表单验证

因为所有的都是必填项,所以涉及到子数组里每一项的校验问题。需要给每个元素添加校验。
先看下这个验证的效果图。

在这里插入图片描述

已知的数据结构:

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' }]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

定义好校验规则,这里只需要设置 :field 在数据对象中的path就行。 :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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/115732
推荐阅读
相关标签
  

闽ICP备14008679号