前言
項目里的一個比較數(shù)據(jù)重復(fù)的功能,根據(jù)勾選的列,選擇表格行數(shù)據(jù),然后點擊高亮重復(fù)項對比當(dāng)前選中的行里面的數(shù)據(jù),拋開業(yè)務(wù)部分這個功能提取后長這樣子

原型評審的時候,產(chǎn)品經(jīng)理就說了一句,這里根據(jù)選擇的列,勾選表格數(shù)據(jù),校驗數(shù)據(jù)重復(fù)
開發(fā)順利開發(fā)完了,測試人員也測試通過標(biāo)記當(dāng)前任務(wù)結(jié)束了,結(jié)果過來一周多,產(chǎn)品經(jīng)理跑過來說,這個功能實現(xiàn)的不對,我要的是 Excel 里面的高亮重復(fù)項功能,像這個操作,噼里啪啦演示了一波,我的天吶,怎么原型評審的時候不這么演示一下呢

項目開發(fā)周期這么緊張,這功能項關(guān)聯(lián)的業(yè)務(wù)邏輯也需要調(diào)整,項目進(jìn)度是不會因為這個功能調(diào)整了就改變上線時間的,還想抓緊時間改,當(dāng)場我就EMO了

思路梳理
工作上的事情不能帶情緒,雖然一萬個不愿意,還是得抽空把產(chǎn)品經(jīng)理的需求給搞定了,我們來看下 Excel 中的高亮重復(fù)項功能的實現(xiàn)效果是怎樣的

通過 WPS Excel 中的操作可以看出,表格數(shù)據(jù)高亮重復(fù)項可以選中一個數(shù)據(jù)列實現(xiàn)當(dāng)前數(shù)據(jù)列
數(shù)據(jù)重復(fù)高亮,也可以多列對比重復(fù)項
代碼實現(xiàn)
根據(jù) Excel 的高亮重復(fù)項操作邏輯我們分析得出,代碼核心實現(xiàn)需要兩個步驟:1.獲取重復(fù)項數(shù)據(jù);2.設(shè)置表格高亮
項目需求功能如下效果

通過實際項目需求操作模式來進(jìn)行分析,首先基本的表格展示,多選功能,高亮列的選中,高亮重復(fù)項操作按鈕, 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">高亮重復(fù)項</el-button>
<el-button @click="clearHighLightData">清除高亮重復(fù)項</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: '趙云'
}
...
表格單元格數(shù)據(jù)高亮是通過設(shè)置的一個自定義變量的來實現(xiàn)的,由于實際項目需求中表格數(shù)據(jù)只有兩列需要高亮顯示,因此這里使用兩個控制變量來實現(xiàn),通過 checkList 選中的 name 值對應(yīng)不同的變量,通過 v-if 的方式控制高亮的 div 背景樣式
接下來,來分析對應(yīng)的操作功能,高亮重復(fù)項功能通過選中數(shù)據(jù)和表格列后,只需要一個點擊,所有的邏輯都在這個這個按鈕的點擊觸發(fā)函數(shù)里完成,開始JS邏輯的實現(xiàn)分析
1.獲取重復(fù)項數(shù)據(jù)
基于選中列和行的對比的表格中的重復(fù)數(shù)據(jù), 高亮重復(fù)項 按鈕點擊后先校驗數(shù)據(jù)行是否選中,以及高亮重復(fù)項的列是否選中,這個是基礎(chǔ)的校驗,所有操作,由于是基于案例分析單獨(dú)寫的 demo,校驗失敗使用的 console.warn
通過 multipleSelection 表格選中行數(shù)據(jù)和 checkList 選中列篩選出重復(fù)項內(nèi)容,得到高亮重復(fù)項數(shù)據(jù)后,接下來獲取到對應(yīng)的行索引并記錄,并把當(dāng)前行對應(yīng)的列的控制變量 back* 設(shè)置為 true
if (this.multipleSelection.length < 2) {
console.warn('先選擇至少兩行數(shù)據(jù)')
return false
}
if (this.checkList.length === 0) {
console.warn('請先選擇一列')
return false
}
// 獲取重復(fù)項內(nèi)容
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) => {
// 設(shè)置重復(fù)項所在的數(shù)據(jù)行
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.設(shè)置表格高亮
上面的步驟中已經(jīng)把當(dāng)前行對應(yīng)的列的控制變量 back* 設(shè)置為 true, 這個時候可以在設(shè)置重復(fù)項所在的數(shù)據(jù)行的同時把當(dāng)前高亮重復(fù)項的標(biāo)記行數(shù)據(jù)替換到綁定的表格數(shù)據(jù)中,這樣可以共用一個循環(huán)
// 更新表格行數(shù)據(jù)為高亮數(shù)據(jù)
const i = this.tableData.findIndex(item => item.id === v.id)
this.tableData.splice(i, 1, v)
這時候?qū)τ谡麄€數(shù)據(jù)層,表格數(shù)據(jù)已經(jīng)根據(jù)選中的行和列對比出高亮的數(shù)據(jù)項了,但是, 此時頁面中的表格并沒有根據(jù)數(shù)據(jù)的變化而重新渲染,手動處理一下表格數(shù)據(jù),讓表格數(shù)據(jù)渲染出高亮設(shè)置后的效果
// 更新表格視圖,實現(xiàn)高亮
const highlightArr = JSON.parse(JSON.stringify(this.tableData))
this.tableData = []
this.tableData = highlightArr
整個表格數(shù)據(jù)列高亮重復(fù)項的功能總算完成了,我們來看下完整的 Demo 操作效果

演示代碼地址
https://github.com/gywgithub/vue-admin-element/blob/main/src/views/Table1.vue
思考總結(jié)
文章中的高亮重復(fù)項是兩列對比,如果是更多列對比,例如表格數(shù)據(jù)是動態(tài)配置列顯示,基于動態(tài)列,動態(tài)查詢指定的數(shù)據(jù),又是動態(tài)自定義高亮重復(fù)項,就像 Excel 表格中的高亮重復(fù)項功能一樣,可以隨便根據(jù)表格數(shù)據(jù)進(jìn)行高亮重復(fù)項操作,像這種情況實現(xiàn)方面的可能就不能參考當(dāng)前文章解決方案了,那遇到這種情況怎么解決呢?
我在做這里的項目需求功能的時候想到過一個思路:根據(jù)表格數(shù)據(jù)行索引和數(shù)據(jù)列索引的方式,去對比數(shù)據(jù)重復(fù)項,根據(jù)數(shù)據(jù)重復(fù)項記錄需要表格中需要高亮的數(shù)據(jù)單元格位置,然后把這些記錄的位置對應(yīng)的單元格進(jìn)行高亮處理
讀者們你們還有別的更好的思路或者實現(xiàn)方案嗎? 歡迎大家評論區(qū)討論交流,一起學(xué)習(xí)共同進(jìn)步 ^-^