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

news2024/12/23 11:05:11

一、需求场景:

有以下一个使用场景,名称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: '' },
    ]
  }]
})

二、解决方法:

可以考虑使用 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:

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

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

方案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>
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']
}

打印结果:

在这里插入图片描述

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

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

在这里插入图片描述

已知的数据结构:

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' }]
}

定义好校验规则,这里只需要设置 :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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/747636.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Javaweb实现ATM机系统开发实战(七)用户密码修改

接下来我们完成密码修改的功能&#xff0c;还是老规矩先看前端界面&#xff1a;这里我们先把需要的变量进行修改&#xff0c;然后把卡号变成不可修改&#xff1a; <% page language"java" contentType"text/html; charsetUTF-8" pageEncoding"UTF-…

深度挖掘文物价值,VR博物馆讲好文物故事

文物不言&#xff0c;自有春秋。丝绸、字画、瓷器、古玩等&#xff0c;铺陈的是传奇&#xff0c;激荡的是灵魂。历史文物珍贵的莫过于其历史与文化的价值&#xff0c;倘若不能被更多的人欣赏、研究、传承&#xff0c;那么这些文物就很难实现“价值外溢”。 单纯的去读历史课本&…

分层解耦-三层架构

三层架构 在上篇文章的案例中写文章-CSDN创作中心 的Controller类承担了对于数据操作&#xff08;访问&#xff09;、对于对于数据的逻辑处理、以及接受请求响应数据的工作&#xff0c;对于类似的小项目来说冗杂程度还可以接收&#xff0c;但是如果项目更加复杂&#xff0c;就…

QT使用同一按钮实现打开/关闭新窗口

QT使用同一按钮实现【打开/关闭】新窗口&#xff0c;实现方案如下&#xff1a; 使用一个全局状态变量记录窗口打开状态通过该状态实现新窗口的show和close 实现代码如下&#xff1a; #include "mainwindow.h" #include "ui_mainwindow.h" #include "…

怎么用PDF24 Tools工具在线进行PDF文件合并

PDF文件是经常会被用到&#xff0c;它在我们的日常生活和工作中扮演着重要的角色。PDF文件合并是将多个PDF文件合并为单个文件&#xff0c;这个过程通常是为了方便管理多个PDF文件&#xff0c;或者将多个PDF文件合并为一个整体以便于共享或打印。既然如此&#xff0c;如何快速合…

达梦sql执行计划、HINT、索引简单应用

目录 收集统计信息. 3 1. 通过DBMS_STATS包中的方法. 3 2、删除指定表的统计信息. 3 执行计划. 3 常用执行计划操作符. 4 统计指定sql执行号的所有操作符的执行时间. 5 HINT 5 并行操作&#xff1a;. 6 查询计划重用、结果集重用. 7 示例. 8 1、收集统计信息&#x…

Comparable/Comparator

现在有一个自定义学生的学生类,里面有name属性,和age属性,我们如何去比较大小? class Student{public String name;public int age;public Student(String name, int age) {this.name name;this.age age;}Overridepublic String toString() {return "Student{" &…

路径规划算法:基于广义正态分布优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于广义正态分布优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于广义正态分布优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用…

关于博客更新的二三事

原文链接&#xff1a;关于博客更新的二三事 前言 很显然&#xff0c;正如大家所见到的&#xff0c;这一版本主题v4.7.0进行了大量的删减工作。可能正如 “大道至简” 吧&#xff0c;相比于前一版本 v3.7.1 &#xff0c;个人认为可能有点花哨&#xff08;仅个人认为&#xff09…

uni-app使用plus本地推送通知栏信息,不使用第三方个推实现消息在线统一推送、消息通知(MQTT、WebSocket、setInterval定时器)

plus.push.createMessage() 因项目一直是运行在内网&#xff0c;所以不支持使用uni-push等运行在公网的第三方个推渠道。 那就只能使用plus.push.createMessage()&#xff0c;示例代码如下&#xff1a; let content "您有一条新的消息~"; let options {"cov…

玩转CSS基础:CSS盒模型

CSS盒模型 什么是CSS盒模型&#xff1f; 完整的 CSS 盒模型应用于块级盒子&#xff0c;内联盒子只使用盒模型中定义的部分内容。模型定义了盒的每个部分 —— margin, border, padding, and content &#xff0c;合在一起就是在页面上看到的内容。为了增加一些额外的复杂性&a…

操作系统Linuxday04

Linux用户相关 Linux是多用户多任务&#xff0c;可以支持多个用户同时登录&#xff0c;并且多个用户可以执行不同的任务&#xff0c;互不影响。 不同的用户&#xff0c;有不同的权限&#xff0c;可以完成权限以内的不同的任务 用户组 如果一次性用户太多&#xff0c;分别给…

【嵌入式Linux项目】基于Linux的全志H616开发板智能垃圾桶项目

目录 一、功能需求 二、涵盖的知识点 1、wiringPi库下的相关硬件操作函数调用 2、线程&#xff08;未使用互斥锁和条件&#xff09; 3、父子进程 4、网络编程&#xff08;socket套接字&#xff09; 5、进程间通信&#xff08;共享内存和信号量&#xff09; 三、开发环境…

[MySQL]MySQL内置函数

[MySQL]MySQL内置函数 文章目录 [MySQL]MySQL内置函数1. 日期函数2. 字符串函数3. 数学函数4. 其他函数 1. 日期函数 常用日期函数如下&#xff1a; 函数名称描述current_date()获取当前日期current_time()获取当前时间current_timestamp()获取当前时间戳now()获取当前日期时…

Redis_安装配置(2)

目录 一、安装redis 1、安装gcc依赖 2、下载并解压安装包 3、编译 4、安装 5、设置全局命令 二、启动redis 1、前台启动 2、后台启动 2.1 修改redis.conf文件 2.2 使用指定配置启动redis 2.3 kill redis的进程 3、开机启动 三、配置redis 远程访问设置 设置密码…

Magic3D: High-Resolution Text-to-3D Content Creation(高分辨率文本到3d内容创建)

Magic3D: High-Resolution Text-to-3D Content Creation&#xff08;高分辨率文本到3d内容创建&#xff09; Paper&#xff1a;https://readpaper.com/pdf-annotate/note?pdfId4738271534435532801&noteId1848084184935912192 Project&#xff1a;https://research.nvidia…

InstructGPT:语言模型的人类反馈指令对齐

论文标题&#xff1a;Training language models to follow instructions with human feedback论文链接&#xff1a;https://arxiv.org/abs/2203.02155论文来源&#xff1a;OpenAI 一、概述 大型语言模型&#xff08;Large language models&#xff0c;LLMs&#xff09;可以通过…

TortoiseGit的安装和使用

1、TortoiseGit的下载安装 安装说明:因为TortoiseGit 只是一个程序壳,必须依赖一个 Git Core,所以安装前请确定已完成git安装和配置。 TortoiseGit下载地址 https://download.tortoisegit.org/tgit/ ,最新稳定版本2.11.0.0。 点进去下载程序包和语言包(非必须),安装时…

【网络】网络基础(一)

目录 一、网络协议初识 1、协议分层 2、OSI七层模型 3、 TCP/IP五层(或四层)模型 4、对网络协议栈的理解 二、网络传输基本流程 1、网络传输流程图 1.1、同一个网段内的两台主机进行文件传输 1.2、跨网段的主机的文件传输 三、数据包封装和分用 四、网络中的地址管理…

配置微服务负载均衡的两种方式

说明&#xff1a;在微服务开发中&#xff0c;每个服务是通过服务名称来区分的&#xff0c;当两个微服务名称相同时&#xff0c;注册中心会视为这两个服务是相同的。配置对应的负载均衡策略&#xff0c;当其他服务发送请求过来的时&#xff0c;可以对这两个微服务进行规则访问。…