前言
在数据分析和数据处理的过程中,经常需要对比两个数据集,以便发现其中的差异和变化。本文将介绍如何使用 el-table 组件来对比两个数据集,并通过差异数据的突显标记,帮助用户更直观地理解数据的变化。
cell-style 属性
其实利用 el-table
组件中的 cell-style
属性处理这个功能非常简单,它允许开发者通过提供对象或返回样式的函数来自定义每个单元格的样式,通过这个特性我们就可以很轻松的实现这个功能。
<el-table :data="productList.tableOne" :cell-style="getCellStyle('参数1', '参数2','...')"></el-table>
核心代码
getCellStyle(currentData, compareToData) {
return ({ rowIndex, column }) => {
const { property } = column;
const currentValue = currentData[rowIndex]?.[property];
const compareToValue = compareToData[rowIndex]?.[property];
return currentValue !== compareToValue ? { color: "red" } : null;
};
},
- 首先,在
getCellStyle
函数中会接受两个参数currentData
和compareToData
。这个函数会返回一个回调函数,用于设置表格单元格的样式; - 回调函数接受一个参数
{ rowIndex, column }
,其中rowIndex
是当前行的索引,column
是当前列的信息。函数内部通过column
获取到属性名property
; - 然后,函数通过索引
rowIndex
和属性名property
从currentData
和compareToData
中获取对应的值currentValue
和compareToValue
; - 最后,函数判断
currentValue
和compareToValue
是否相等,如果不相等,则返回一个样式对象{ color: "red" }
,表示将单元格的文字颜色设置为红色;如果相等,则返回null
,表示不设置样式。
实现效果
完整功能代码
index.vue
<template>
<div>
<el-button type="success" @click="version">版本对比</el-button>
<div>
<select-dialog
:dialogChild.sync="selectDialog.dialogLsattr"
:dialogRow="selectDialog.dialogRow"
/>
</div>
</div>
</template>
<script>
import selectDialog from "./components/selectDialog";
export default {
components: {
"select-dialog": selectDialog,
},
data() {
return {
selectDialog: {
dialogRow: {},
dialogLsattr: false,
},
};
},
methods: {
version() {
this.selectDialog.dialogLsattr = true;
},
},
};
</script>
components/selectDialog.vue
<template>
<el-dialog
title="版本选择"
width="40%"
:close-on-click-modal="false"
:visible.sync="dialogVisible"
@close="close"
>
<div class="selectCon">
<div class="transfer">
<div class="nav">
<div class="title">
<span>版本列表</span>
<span>{{ count }}/{{ list.length }}</span>
</div>
<div class="search">
<el-input
v-model="searchVal"
clearable
prefix-icon="el-icon-search"
placeholder="版本号"
@input="searchVersions"
></el-input>
</div>
</div>
<div class="checkboxs">
<div
v-for="(item, index) in searchVal ? searchResult : list"
:key="index"
@click="toggleCheckbox(item)"
>
<el-checkbox
v-model="checked[item]"
:disabled="count >= 2 && !checked[item]"
@change="toggleCheckbox(item)"
>{{ item }}</el-checkbox
>
</div>
<el-empty
v-if="!list.length || (searchVal && !searchResult.length)"
description="暂无数据"
></el-empty>
</div>
</div>
<div class="subBtn">
<el-button type="primary" :disabled="count < 2" @click="submit"
>对比</el-button
>
<el-button
style="margin-left: 10px"
@click="$emit('update:dialogChild', false)"
>取消</el-button
>
</div>
</div>
<div>
<details-drawer
:drawerChild.sync="detailsDrawer.drawerLsattr"
:drawerRow="detailsDrawer.drawerRow"
/>
</div>
</el-dialog>
</template>
<script>
import detailsDrawer from "./detailsDrawer";
export default {
components: {
"details-drawer": detailsDrawer,
},
props: {
dialogChild: {
type: Boolean,
default: function () {
return false;
},
},
dialogRow: {
type: Object,
default: function () {
return {};
},
},
},
data() {
return {
searchVal: "", //搜索值
checked: {}, //选中的checkbox
list: [
"version1",
"version2",
"version3",
"version4",
"version5",
"version6",
"version7",
"version8",
"version9",
"version10",
"version11",
"version12",
"version13",
"version14",
"version15",
"version16",
], //模拟全部数据列表
searchResult: [], // 搜索结果列表
dialogVisible: false, //弹框状态
detailsDrawer: {
//抽屉传递数据
drawerRow: {},
drawerLsattr: false,
},
};
},
computed: {
// 动态计算当前选中的checkbox数量
count: function () {
return Object.values(this.checked).filter(Boolean).length;
},
},
watch: {
dialogChild: {
handler(newName, oldName) {
this.dialogVisible = newName;
this.list.forEach((item) => {
this.$set(this.checked, item, false);
});
},
deep: true,
},
dialogRow: {
handler(newName, oldName) {},
deep: true,
},
},
methods: {
// 当前行切换复选框的选中状态
toggleCheckbox(item) {
if (!(this.count >= 2 && !this.checked[item])) {
this.checked[item] = !this.checked[item];
}
},
// 搜索
searchVersions() {
const keyword = this.searchVal.trim(); // 获取输入框的值并去除首尾空格
if (keyword === "") {
this.searchResult = [];
return;
}
this.searchResult = this.list.filter((item) => item.includes(keyword));
console.log("搜索结果:", this.searchResult);
},
// 对比
submit() {
console.log(this.checked);
this.detailsDrawer.drawerLsattr = true;
},
// 关闭弹框
close() {
this.$emit("update:dialogChild", false);
this.checked = {};
this.searchVal = "";
this.searchResult = [];
},
},
};
</script>
<style lang="less" scoped>
.selectCon {
background-color: #fff;
padding: 16px;
.transfer {
width: 100%;
height: 50vh;
overflow-y: auto;
border-radius: 6px;
border: 1px solid #ebeef5;
.nav {
position: sticky;
top: 0;
z-index: 10;
background: #fff;
.title {
background: #f5f7fa;
padding: 10px 16px;
display: flex;
justify-content: space-between;
span:nth-child(1) {
font-weight: bold;
}
span:last-child {
color: #909399;
}
}
.search {
padding: 10px 16px 0 16px;
.el-input {
width: 100%;
}
}
}
.checkboxs {
padding: 10px 16px;
div:hover {
cursor: pointer;
background: #f5f7fa;
}
.el-checkbox {
margin: 3px 6px;
}
.el-checkbox:hover {
color: #296bff;
}
}
}
.subBtn {
margin-top: 16px;
display: flex;
justify-content: right;
}
}
</style>
components/detailsDrawer.vue
<template>
<el-drawer
:append-to-body="true"
:close-on-click-modal="false"
:visible.sync="drawerVisible"
direction="rtl"
size="100%"
title="版本对比"
@close="$emit('update:drawerChild', false)"
>
<div class="versionsCon">
<h4>标题1</h4>
<el-card class="box-card">
<div class="itemContrast">
<el-table
:data="productList.tableOne"
border
:cell-style="
getCellStyle(productList.tableOne, productList.tableTwo)
"
>
<el-table-column prop="aaa" label="名称1"></el-table-column>
<el-table-column prop="bbb" label="名称2"> </el-table-column>
<el-table-column prop="ccc" label="名称3"></el-table-column>
</el-table>
<el-table
:data="productList.tableTwo"
border
:cell-style="
getCellStyle(productList.tableOne, productList.tableTwo)
"
>
<el-table-column prop="aaa" label="名称1"></el-table-column>
<el-table-column prop="bbb" label="名称2"> </el-table-column>
<el-table-column prop="ccc" label="名称3"></el-table-column>
</el-table>
</div>
</el-card>
<h4>标题2</h4>
<el-card class="box-card">
<div class="itemContrast">
<el-table
:data="inventoryList.tableOne"
border
:cell-style="
getCellStyle(inventoryList.tableOne, inventoryList.tableTwo)
"
>
<el-table-column prop="aaa" label="名称1"></el-table-column>
<el-table-column prop="bbb" label="名称2"> </el-table-column>
<el-table-column prop="ccc" label="名称3"></el-table-column>
<el-table-column prop="ddd" label="名称4"></el-table-column>
</el-table>
<el-table
:data="inventoryList.tableTwo"
border
:cell-style="
getCellStyle(inventoryList.tableOne, inventoryList.tableTwo)
"
>
<el-table-column prop="aaa" label="名称1"></el-table-column>
<el-table-column prop=