最近接到一个需求,是这样的,在列表里面,一些敏感的数据是不能查看的,增加一个小眼睛,能够查看脱敏的数据,当时觉得,好像没有那么复杂的哈,就是点击去改变一个变量,相对应的赋值就好了,大体的想法确实没有错,但是项目里真的那么简单吗,我们现在就来看一下。
1.我发现列表的column是动态渲染的,也就是说不是固定的,有一个功能是自定义列的,所以在这个功能之外,我们就不能再指定el-table-column里面进行一个插槽的动态添加了,所以是需要判断在哪一列里面进行添加小眼睛的功能。
这时候我们判断出在指定列了,因为是遍历出来的,除了当前的这个我们利用作用域的插槽进行取值,那其他的列呢,我也尝试了挺多的办法,在接口返回的数据进行组装,让列表可以渲染出来等等,但都不尽如意,我就去查找了文档,
找到了scope.column.property,作用域插槽里面可以拿到我们定义的prop的值,这就好办了,我们都知道,我们的scope.row相当于element给我们做了一层的遍历,所以我们可以利用scope.row.属性,拿到值,所以我们就可以这么写 scope.row[scope.column.property] ,列表遍历渲染的时候,就可以动态的进行渲染其他列里面的数据了.
<el-table-column
v-for="(item,index) in tableShowColumn"
:key="index"
:prop="item.prop"
:label="item.label"
:width="item.width"
show-overflow-tooltip>
<template slot-scope="scope">
<template v-if="item.prop==='receiverTel'">
<span>{{ scope.row.receiverTel }}</span>
</template>
<template v-else>
{{scope.row[scope.column.property] }}
</template>
</template>
</el-table-column>
tableColumns的数据
2.好,现在我们第一步完成了,我们就需要在receiverTel这一列里面添加小眼睛的功能了,我们需要给每一个小眼睛添加一个变量,让每次点击的时候控制不同的变量,我们才能赋值到指定的行里面去。
iconStaus:{}
3.我们需要在调取接口的时候,动态的往iconStaus添加值为false。
for (let i = 0; i < res.data.list.length; i++) {
this.iconStaus = {
i: false
}
}
4.我们数据的索引要跟我们表格行的索引要对应上,我们需要给scope.row添加index,我们得让列表知道,点击的小眼睛对应哪一行
:row-class-name="rowClassName" //el-table的属性
rowClassName({ row, rowIndex }) {
row.$index = rowIndex
},
5.
我们开始写点击小眼睛的事件了,点开的时候调取接口,进行赋值,关闭的时候需要把之前的数据在赋值回去,对吧,
所以我们需要对接口返回的数据进行深拷贝,如果不是深拷贝的话,我们调取脱敏接口返回的数据就会把原来的值给覆盖掉,这显然不是我们想要的
深拷贝:大家返回的数据接口如果只有一层的话,可以时候扩展运算符,获取JSON的方式,但是对于列表的话,我们可以使用lodash里面的cloneDeep的方法,具体怎么实现,大家可以集思广益,或者百度,
我这实现一种深拷贝的方式。
function deepClone(source) {
if (!source && typeof source !== 'object') {
throw new Error('error arguments', 'deepClone')
}
const targetObj = source.constructor === Array ? [] : {}
Object.keys(source).forEach(keys => {
if (source[keys] && typeof source[keys] === 'object') {
targetObj[keys] = deepClone(source[keys])
} else {
targetObj[keys] = source[keys]
}
})
return targetObj
}
在接口返回的数据里进行使用
this.orderData = { ...res.data }
this.temporaryOrderList = deepClone(res.data.list) //作为临时的存储用来,关闭的时候进行赋值
// 根据列表length,动态的生成属性,绑定小眼睛
for (let i = 0; i < res.data.list.length; i++) {
this.iconStaus = {
i: false
}
template里面
<span @click="eyeIsShowHandle(scope.row)">
<svg-icon
:icon-class="iconStaus[scope.row.$index]?'eye-open' : 'eye'"
/>
</span>
在代码里体现详细步骤
async eyeIsShowHandle({ $index, orderNo, billCode, receiverTel, senderTel }) {
1.首先点击的时候,我们取反列表里对应的值
// 因为是复杂类型,改变值必须用$set,否则列表不刷新
this.$set(this.iconStaus, $index, !this.iconStaus[$index])
2.判断 true的时候调取接口,进行赋值
//
if (this.iconStaus[$index]) {
try {
const param = {
orderNo,
billCode,
receiverTel,
senderTel
}
const { code, data } = await this.$Api.order.getWaybillDesensitizationData(param)
if (code === 200 && data.length > 0) {
this.orderData.list.forEach((item, index) => {
data.forEach(subItem => {
if (item.billCode === subItem.billCode) {
this.$set(this.orderData.list[index], 'receiverTel', subItem.receiverTel)
}
})
})
} else {
// 关闭小眼睛
this.$set(this.iconStaus, $index, false)
}
} catch (error) {
console.log('🚀 ~ file: index.vue:751 ~ eyeIsShowHandle ~ error', error)
}
} else {
3.// 临时存储 为false时赋值
const tel = this.temporaryOrderList[$index].receiverTel
this.$set(this.orderData.list[$index], 'receiverTel', tel)
}
},
这时候产品又说,在弹窗的详情里面也加上,立马安排,
我们这种事点击行里面的每一条数据,进行弹窗展示详情,基本逻辑都是大同小异的哈,
我们在dialog的open事件里,进行调取接口拿出,返回的数据,深拷贝出来,存储到临时的变量里,比每次点击小眼镜的时候调取接口的时候写法更简单,而且体验正好,我们这一行的得学会偷懒是吧. 咳咳,步入正题。
//在dialog的open事件里
@open="dialogDesensitizationData"
methods里
async dialogDesensitizationData() {
const { orderNo, billCode, receiverTel, senderTel } = this.detailData
try {
const param = {
orderNo,
billCode,
receiverTel,
senderTel
}
const { code, data } = await this.$Api.order.getWaybillDesensitizationData(param)
if (code === 200 && data.length > 0) {
data.forEach(item => {
if (item.billCode === billCode) {
this.dialogTemporaryObj = item
}
})
} else {
// 关闭小眼睛
this.addresseeIconFlag = false //小眼睛绑定的
this.senderIconFlag = false
}
} catch (error) {
console.log('🚀 ~ file: index.vue:759 ~ dialogDesensitizationData ~ error', error)
}
},
// 在详情里,点击小眼睛的事件,最近迷恋上了switch,如果判断的条件过多,会导致代码可读性很差,当然可以有更好的设计思想,但是我菜,就近取舍了,
viewPhone(status) {
const { $index } = this.detailData //点击行,传过来的数据,要进行深拷贝哦
// 临时存储 为false时赋值
const temporary = this.temporaryOrderList[$index]
switch (status) {
case 'sender':
this.senderIconFlag = !this.senderIconFlag
// icon打开
if (this.senderIconFlag) {
this.$set(this.detailData, 'senderTel', this.dialogTemporaryObj.senderTel)
} else {
// icon关闭
this.detailData.senderTel = temporary.senderTel
}
break
case 'addressee':
this.addresseeIconFlag = !this.addresseeIconFlag
if (this.addresseeIconFlag) {
this.$set(this.detailData, 'receiverTel', this.dialogTemporaryObj.receiverTel)
} else {
this.detailData.receiverTel = temporary.receiverTel
}
break
}
},
好了,需求完成了哦,我觉得,当下确实有时候很想尝试一下新的写法,包括一些新的思路,写博客呢,我也不在乎浏览量,点赞什么的,只不过是想记录当下的状态,毕竟记忆随着时间会逐渐消失的,但是把当时记录下的笔记,不会,在这里送大家一句话哦,"爱出者爱返,福往者福来",希望大家能够开开心心的工作,快快乐乐的生活,毕竟生活是自己的。