需求:新旧数据对比,以表格展示两组数据差异的地方
1) 删除的数据在旧数据表格中整行显示红色背景
2) 新增的数据在新数据表格中整行显示黄色背景
3) 修改的数据在单个单元格中显示橙色背景
直接上代码:
<div class="table-container">
<!-- 原始数据表格 -->
<table border class="tableBox">
<thead>
<tr>
<th v-for="(header, index) in headers" :key="index">{{ header }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, rowIndex) in originalData" :key="rowIndex" :class="{ 'deleted': isDeleted(rowIndex) }">
<td v-for="(cell, cellKey) in row" :key="cellKey">
{{ cell }}
</td>
</tr>
</tbody>
</table>
<!-- 新数据表格 -->
<table border class="tableBox">
<thead>
<tr>
<th v-for="(header, index) in headers" :key="index">{{ header }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, rowIndex) in newData" :key="rowIndex" :class="{ 'added': isAdded(rowIndex) }">
<td v-for="(cell, cellKey) in row" :key="cellKey" :class="{ 'modified': isModified(rowIndex, cellKey) && !isAdded(rowIndex) }">
{{ cell }}
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data() {
return {
headers: ['下筒模式', '程序类型', '程序总时长', '下筒洗涤温度', '下筒漂洗次数', '其他信息', '下筒主洗涤时间设置(增/减)'],
originalData: [
{ mode: '标准', type: '日常', duration: '60分钟', temp: '30℃', rinse: '2次', otherInfo: '标准清洗', timeAdjust: '+10' },
{ mode: '节能', type: '深度', duration: '90分钟', temp: '40℃', rinse: '3次', otherInfo: '深层清洁', timeAdjust: '-5' },
{ mode: '快速', type: '轻柔', duration: '30分钟', temp: '20℃', rinse: '1次', otherInfo: '快速洗涤', timeAdjust: '+0' }
],
newData: [
{ mode: '标准', type: '日常', duration: '60分钟', temp: '30℃', rinse: '2次', otherInfo: '标准清洗', timeAdjust: '+15' }, // 修改的数据
{ mode: '节能', type: '深度', duration: '120分钟', temp: '40℃', rinse: '3次', otherInfo: '深层清洁', timeAdjust: '-5' }, // 修改的数据
{ mode: '强力', type: '除菌', duration: '180分钟', temp: '60℃', rinse: '4次', otherInfo: '高温杀菌', timeAdjust: '+30' } // 新增的数据
]
}
},
methods: {
// 判断是否为修改数据
isModified(rowIndex, cellKey) {
const origCell = this.originalData[rowIndex]?.[cellKey]
const newCell = this.newData[rowIndex]?.[cellKey]
return origCell !== newCell
},
// 判断是否为删除数据
isDeleted(rowIndex) {
const mode = this.originalData[rowIndex]?.mode
return !this.newData.some(newRow => newRow.mode === mode)
},
// 判断是否为新增数据
isAdded(rowIndex) {
const mode = this.newData[rowIndex]?.mode
return !this.originalData.some(origRow => origRow.mode === mode)
}
}
}
</script>
<style scoped>
.modified {
background-color: orange !important; /* 修改的数据 */
}
.deleted {
background-color: red !important; /* 删除的数据 */
}
.added {
background-color: yellow !important; /* 新增的数据 */
}
.tableBox{
text-align: center;
td{
padding: 10px;
}
}
</style>
增加需求点:以每行第一列为判断点,不看顺序
直接上代码:
<div class="table-container">
<table>
<thead>
<tr>
<th v-for="(header, index) in headers" :key="index">{{ header }}</th>
</tr>
</thead>
<tbody>
<tr
v-for="(row) in originalData"
:key="row.mode"
:class="{ 'deleted': isDeleted(row.mode) }">
<td v-for="(cell, cellKey) in row" :key="cellKey">
{{ cell }}
</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th v-for="(header, index) in headers" :key="index">{{ header }}</th>
</tr>
</thead>
<tbody>
<tr
v-for="(row, rowIndex) in newData"
:key="row.mode"
:class="{ 'added': isNew(row.mode) }">
<td
v-for="(cell, cellKey) in row"
:key="cellKey"
:class="{ 'modified': isModified(rowIndex, cellKey) }">
{{ cell }}
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data() {
return {
headers: [
'下筒模式',
'程序类型',
'程序总时长',
'下筒洗涤温度',
'下筒漂洗次数',
'其他信息',
'下筒主洗涤时间设置(增/减)'
],
originalData: [
{
mode: '标准',
type: '日常',
duration: '60分钟',
temp: '30℃',
rinse: '2次',
otherInfo: '标准清洗',
timeAdjust: '+10'
},
{
mode: '快速',
type: '轻柔',
duration: '30分钟',
temp: '20℃',
rinse: '1次',
otherInfo: '快速洗涤',
timeAdjust: '+0'
},
{
mode: '节能',
type: '深度',
duration: '90分钟',
temp: '40℃',
rinse: '3次',
otherInfo: '深层清洁',
timeAdjust: '-5'
}
],
newData: [
{
mode: '标准',
type: '日常',
duration: '60分钟',
temp: '30℃',
rinse: '2次',
otherInfo: '标准清洗',
timeAdjust: '+15'
}, // 修改的数据
{
mode: '节能',
type: '深度',
duration: '120分钟',
temp: '40℃',
rinse: '3次',
otherInfo: '深层清洁',
timeAdjust: '-5'
}, // 修改的数据
// {
// mode: '快速',
// type: '轻柔',
// duration: '30分钟',
// temp: '20℃',
// rinse: '1次',
// otherInfo: '快速洗涤',
// timeAdjust: '+0'
// }, // 未修改的数据
{
mode: '强力',
type: '除菌',
duration: '180分钟',
temp: '60℃',
rinse: '4次',
otherInfo: '高温杀菌',
timeAdjust: '+30'
} // 新增的数据
]
}
},
computed: {
statusMap() {
const status = {}
this.originalData.forEach(row => {
status[row?.mode] = {
mode: row?.mode,
deleted: true,
modified: {}
}
})
this.newData.forEach(row => {
const mode = row?.mode
if (status[mode]) {
status[mode].deleted = false // 已经存在于原始数据中,不是删除的
const origRow = this.originalData.find(
origRow => origRow?.mode === mode
)
if (origRow) {
for (const key in row) {
if (key === 'mode') continue // 不比较 mode 字段
status[mode].modified[key] = origRow[key] !== row[key]
}
}
} else {
status[mode] = {
mode: mode,
added: true, // 新增的数据
modified: {}
}
}
})
console.log(status)
return status
}
},
methods: {
isDeleted(mode) {
const entry = this.statusMap[mode]
return entry && entry.deleted
},
isNew(mode) {
const entry = this.statusMap[mode]
return entry && entry.added
},
isModified(rowIndex, cellKey) {
const row = this.newData[rowIndex]
if (!row || !row?.mode) {
return false
}
const mode = row?.mode
const entry = this.statusMap[mode]
return entry && entry?.modified[cellKey]
}
}
}
</script>
<style scoped>
.modified {
background-color: orange !important; /* 修改的数据 */
}
.deleted {
background-color: red !important; /* 删除的数据 */
}
.added {
background-color: yellow !important; /* 新增的数据 */
}
.tableBox{
text-align: center;
td{
padding: 10px;
}
}
</style>