前言
项目里的一个比较数据重复的功能,根据勾选的列,选择表格行数据,然后点击高亮重复项对比当前选中的行里面的数据,抛开业务部分这个功能提取后长这样子
原型评审的时候,产品经理就说了一句,这里根据选择的列,勾选表格数据,校验数据重复
开发顺利开发完了,测试人员也测试通过标记当前任务结束了,结果过来一周多,产品经理跑过来说,这个功能实现的不对,我要的是 Excel 里面的高亮重复项功能,像这个操作,噼里啪啦演示了一波,我的天呐,怎么原型评审的时候不这么演示一下呢
项目开发周期这么紧张,这功能项关联的业务逻辑也需要调整,项目进度是不会因为这个功能调整了就改变上线时间的,还想抓紧时间改,当场我就EMO了
思路梳理
工作上的事情不能带情绪,虽然一万个不愿意,还是得抽空把产品经理的需求给搞定了,我们来看下 Excel 中的高亮重复项功能的实现效果是怎样的
通过 WPS Excel 中的操作可以看出,表格数据高亮重复项可以选中一个数据列实现当前数据列
数据重复高亮,也可以多列对比重复项
代码实现
根据 Excel 的高亮重复项操作逻辑我们分析得出,代码核心实现需要两个步骤:1.获取重复项数据;2.设置表格高亮
项目需求功能如下效果
通过实际项目需求操作模式来进行分析,首先基本的表格展示,多选功能,高亮列的选中,高亮重复项操作按钮, vue
文件中 template
代码如下
<el-table
border
ref="multipleTable"
:data="tableData"
@selection-change="handleSelectionChange"
style="width: 500px"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column label="日期">
<template slot-scope="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column label="姓名">
<template slot-scope="scope">
<div
v-if="scope.row.back"
class="background-color-ffff00"
>
{{ scope.row.name }}
</div>
<div v-else>{{ scope.row.name }}</div>
</template>
</el-table-column>
<el-table-column label="昵称">
<template slot-scope="scope">
<div
v-if="scope.row.back2"
class="background-color-ffff00"
>
{{ scope.row.nickName }}
</div>
<div v-else>{{ scope.row.nickName }}</div>
</template>
</el-table-column>
</el-table>
<div style="margin-top: 20px; display: flex">
<el-checkbox-group
v-model="checkList"
style="margin-right: 20px; margin-top: 10px"
>
<el-checkbox label="name">姓名</el-checkbox>
<el-checkbox label="nickName">昵称</el-checkbox>
</el-checkbox-group>
<el-button @click="highLightData">高亮重复项</el-button>
<el-button @click="clearHighLightData">清除高亮重复项</el-button>
</div>
<script>
export default {
name: 'Table1',
components: {},
data () {
return {
checkList: [],
tableData: [
{
id: '1',
date: '2016-05-03',
name: '张三',
nickName: '李四'
},
{
id: '2',
date: '2016-05-02',
name: '李四',
nickName: '曹操'
},
{
id: '3',
date: '2016-05-04',
name: '张三',
nickName: '赵云'
}
...
表格单元格数据高亮是通过设置的一个自定义变量的来实现的,由于实际项目需求中表格数据只有两列需要高亮显示,因此这里使用两个控制变量来实现,通过 checkList
选中的 name
值对应不同的变量,通过 v-if
的方式控制高亮的 div
背景样式
接下来,来分析对应的操作功能,高亮重复项功能通过选中数据和表格列后,只需要一个点击,所有的逻辑都在这个这个按钮的点击触发函数里完成,开始JS逻辑的实现分析
1.获取重复项数据
基于选中列和行的对比的表格中的重复数据, 高亮重复项
按钮点击后先校验数据行是否选中,以及高亮重复项的列是否选中,这个是基础的校验,所有操作,由于是基于案例分析单独写的 demo,校验失败使用的 console.warn
通过 multipleSelection
表格选中行数据和 checkList
选中列筛选出重复项内容,得到高亮重复项数据后,接下来获取到对应的行索引并记录,并把当前行对应的列的控制变量 back*
设置为 true
if (this.multipleSelection.length < 2) {
console.warn('先选择至少两行数据')
return false
}
if (this.checkList.length === 0) {
console.warn('请先选择一列')
return false
}
// 获取重复项内容
const arr = []
const arr2 = []
this.multipleSelection.forEach((v, k) => {
this.checkList.forEach(v2 => {
if (arr.indexOf(v[v2]) === -1) {
arr.push(v[v2])
} else {
if (arr2.indexOf(v[v2]) === -1) {
arr2.push(v[v2])
}
}
})
})
console.log('arr --xxx ', arr)
console.log('arr2 -- ', arr2)
this.multipleSelection.forEach((v, k) => {
// 设置重复项所在的数据行
arr2.forEach(item => {
this.checkList.forEach(v2 => {
if (v2 === 'name') {
if (item === v[v2]) {
v.back = true
}
}
if (v2 === 'nickName') {
if (item === v[v2]) {
v.back2 = true
}
}
})
})
})
2.设置表格高亮
上面的步骤中已经把当前行对应的列的控制变量 back*
设置为 true
, 这个时候可以在设置重复项所在的数据行的同时把当前高亮重复项的标记行数据替换到绑定的表格数据中,这样可以共用一个循环
// 更新表格行数据为高亮数据
const i = this.tableData.findIndex(item => item.id === v.id)
this.tableData.splice(i, 1, v)
这时候对于整个数据层,表格数据已经根据选中的行和列对比出高亮的数据项了,但是, 此时页面中的表格并没有根据数据的变化而重新渲染,手动处理一下表格数据,让表格数据渲染出高亮设置后的效果
// 更新表格视图,实现高亮
const highlightArr = JSON.parse(JSON.stringify(this.tableData))
this.tableData = []
this.tableData = highlightArr
整个表格数据列高亮重复项的功能总算完成了,我们来看下完整的 Demo 操作效果
演示代码地址
https://github.com/gywgithub/vue-admin-element/blob/main/src/views/Table1.vue
思考总结
文章中的高亮重复项是两列对比,如果是更多列对比,例如表格数据是动态配置列显示,基于动态列,动态查询指定的数据,又是动态自定义高亮重复项,就像 Excel 表格中的高亮重复项功能一样,可以随便根据表格数据进行高亮重复项操作,像这种情况实现方面的可能就不能参考当前文章解决方案了,那遇到这种情况怎么解决呢?
我在做这里的项目需求功能的时候想到过一个思路:根据表格数据行索引和数据列索引的方式,去对比数据重复项,根据数据重复项记录需要表格中需要高亮的数据单元格位置,然后把这些记录的位置对应的单元格进行高亮处理
读者们你们还有别的更好的思路或者实现方案吗? 欢迎大家评论区讨论交流,一起学习共同进步 ^-^