vue多层级复杂数据结构的新旧数据对比方法

本文主要是介绍vue多层级复杂数据结构的新旧数据对比方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近做的项目里有个需求:审批页需要把修改前和修改后的数据进行对比,有变化的数据需要标红显示,鼠标移入的时候显示变更前的数据和变更后的数据,新增的整条数据也要标红,效果如下:

后台返回的报文结构包含:字符串、数组、对象、数组嵌套对象、对象嵌套对象的形式,示例如下:

{newData: {skuName: 'test',number: '20230720',skuBasicInfo: {id: 1,name: 'test',label: '已上架',info: { fileName: '申请表.doc', code: '123' }},skuSettleList: [{ settleNum: '001', desc: '通讯费',  type: '3' },{ settleNum: '002', desc: '交通费',  type: '1' },{ settleNum: '005', desc: '住宿费',  type: '6' }],skuMsg: { ownPhone: '13323452345', ownEmail: '123@456.com' },province: ['100', '110', '230'],createBy: 'admin',createTime: '2023-07-20 14:29:18',},oldData: {skuName: 'test',number: '20230720',skuBasicInfo: {id: 1,name: 'test',label: '失效',info: { fileName: '产品信息表.doc', code: '123' }},skuSettleList: [{ settleNum: '001', desc: '通讯费',  type: '3' },{ settleNum: '002', desc: '餐补费',  type: '5' },],skuMsg: { ownPhone: '15534568765', ownEmail: '123@456.com' },province: ['100'],createBy: 'admin',createTime: '2023-07-20 14:29:18',}
}

 考虑到存在删除整条数据后又新增整条数据的情况,像skuSettleList字段里的数据,就需要取一个唯一标识,根据唯一标识分别取newData和oldData里的数据进行比对,将比对结果存入一个新的字段isChange内,作为判断新增还是老数据变更的标识。

整体思路如下:

以newData的key为准,循环+递归逐层比对,如果有新增数据,则在自增的数据上加isChange字段,赋值为1表示新增;如果是旧数据变更,则在newData的同层级添加'_old'+key,赋值为oldData[key]的值。

1、循环遍历newData的第一层key,先判断newData[key]是否为null,如果是则不走判断逻辑,如果不是则进入下一步判断;

2、判断newData[key]的数据类型,此时会出现三种情况:基本数据类型、对象、数组。

  • 如果是基本数据类型,则直接比对newData[key]和oldData[key];
  • 如果是对象,则调用方法本身,以newData[key]和oldData[key]作为方法的入参;
  • 如果是数组,则需要考虑两种情况:有新增数据、只有旧数据变更。

 页面结构大致如下:

<el-table :data="tableData" :row-class-name="tableRowClassName"><el-table-column label="商品名称"><template slot-scope="scope"><el-popoverplacement="top-start"width='330'offset='115'visible-arrowv-if="scope.row._oldskuName"trigger="hover"><PopoverBox :new-data="scope.row.skuName" :old-data="scope.row._oldskuName"/><span slot="reference">{{ scope.row.skuName }}</span></el-popover><span v-else>{{ scope.row.skuName }}</span></template></el-table-column>
</el-table>

方法完整代码如下:

function compareDataNew(newData, oldData) {// 创建一个数组,用于保存需要特殊判断的字段名const specialKeys = ['skuSettleList', 'skuTemplateList']// 创建一个数组,用于保存specialKeys里对应索引字段数据的唯一标识,要和specialKeys的元素一一对应const judgeIds = ['settleNum', 'templateNum']// 遍历newData的第一层keyfor (const key in newData) {// 判断当前key是否为null,为null不走判断逻辑,否则进入类型判断if (newData[key]) {// 第一层数据为数组的情况if (newData[key].constructor === Array) {// 判断是否为空数组,为空则不走判断逻辑if (newData[key].length) {// 判断当前数组是基本数据类型还是引用对象类型// 此处没考虑数组内元素类型复杂的情况,例如基本数据类型和引用数据类型都存在,且第一个元素为基本数据类型const item = newData[key][0]// 此处的判断没有考虑二维数组的情况if (item.constructor === Object) {// 如果是对象类型,则遍历每一个对象for (let a = 0; a < newData[key].length; a++) {// 先判断当前key是否属于specialKeys,如果是再进入后续逻辑const judgeIndex = specialKeys.indexOf(key)if (judgeIndex !== -1) {// 获取数据的唯一标识字段const judgeId = judgeIds[judgeIndex]// 给newData[key][a]这条数据添加标识字段isChange,默认值1// 1--新增  0--旧数据变更newData[key][a]['isChange'] = 1// 遍历oldData[key],如果judgeId在oldData中不存在,则说明就是新增数据,如果存在则是旧数据变更for (let b = 0; b < oldData[key].length; b++) {if (newData[key][a][judgeId] === oldData[key][b][judgeId]) {newData[key][a]['isChange'] = 0// 旧数据变更的话,需要逐个比对每一条数据的每个值是否相等,所以需要再次调用自身compareDataNew(newData[key][a], oldData[key][b])}}} else {// 当前key不属于specialKeys,不需要特殊处理,所以直接递归调用自身即可compareDataNew(newData[key][a], oldData[key][a])}}continue}// 走到此处说明当前数组是个基本类型的数组,直接对比数组长度// 此处没考虑长度相等但元素不同的情况!!!if (newData[key].length !== oldData[key].length) {newData['_old' + key] = oldData[key]}} else {// 进入这一层说明新数组数据都已经删除了,删除的数据页面不会展示,此处只是保留一下旧数据if (oldData[key].length) {newData['_old' + key] = oldData[key]}}continue}// 第一层数据为对象的情况下,再次调用自身进行第二层数据的比对if (newData[key].constructor === Object) {compareDataNew(newData[key], oldData[key])continue}// 第一层数据为基本数据类型的情况下,直接对比值即可if (newData[key] !== oldData[key]) {newData['_old' + key] = oldData[key]}}}
}

📢📢📢 注意!!!

由于这个方法是基于公司业务情景写的,所以有些情况并未考虑到,例如复杂的数组嵌套、数组内存在多种数据类型的元素、二维数组等,判断并不全面,大家可以根据自己的实际需求完善判断逻辑,本文章仅作记录和思路分享~

这篇关于vue多层级复杂数据结构的新旧数据对比方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/344515

相关文章

Java注解之超越Javadoc的元数据利器详解

《Java注解之超越Javadoc的元数据利器详解》本文将深入探讨Java注解的定义、类型、内置注解、自定义注解、保留策略、实际应用场景及最佳实践,无论是初学者还是资深开发者,都能通过本文了解如何利用... 目录什么是注解?注解的类型内置注编程解自定义注解注解的保留策略实际用例最佳实践总结在 Java 编程

一文教你Python如何快速精准抓取网页数据

《一文教你Python如何快速精准抓取网页数据》这篇文章主要为大家详细介绍了如何利用Python实现快速精准抓取网页数据,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解下... 目录1. 准备工作2. 基础爬虫实现3. 高级功能扩展3.1 抓取文章详情3.2 保存数据到文件4. 完整示例

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

判断PyTorch是GPU版还是CPU版的方法小结

《判断PyTorch是GPU版还是CPU版的方法小结》PyTorch作为当前最流行的深度学习框架之一,支持在CPU和GPU(NVIDIACUDA)上运行,所以对于深度学习开发者来说,正确识别PyTor... 目录前言为什么需要区分GPU和CPU版本?性能差异硬件要求如何检查PyTorch版本?方法1:使用命

python处理带有时区的日期和时间数据

《python处理带有时区的日期和时间数据》这篇文章主要为大家详细介绍了如何在Python中使用pytz库处理时区信息,包括获取当前UTC时间,转换为特定时区等,有需要的小伙伴可以参考一下... 目录时区基本信息python datetime使用timezonepandas处理时区数据知识延展时区基本信息

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

SpringMVC 通过ajax 前后端数据交互的实现方法

《SpringMVC通过ajax前后端数据交互的实现方法》:本文主要介绍SpringMVC通过ajax前后端数据交互的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价... 在前端的开发过程中,经常在html页面通过AJAX进行前后端数据的交互,SpringMVC的controll

Java中的工具类命名方法

《Java中的工具类命名方法》:本文主要介绍Java中的工具类究竟如何命名,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java中的工具类究竟如何命名?先来几个例子几种命名方式的比较到底如何命名 ?总结Java中的工具类究竟如何命名?先来几个例子JD

Spring Security自定义身份认证的实现方法

《SpringSecurity自定义身份认证的实现方法》:本文主要介绍SpringSecurity自定义身份认证的实现方法,下面对SpringSecurity的这三种自定义身份认证进行详细讲解,... 目录1.内存身份认证(1)创建配置类(2)验证内存身份认证2.JDBC身份认证(1)数据准备 (2)配置依