持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情
什么是weakMap
WeakMap结构与Map结构类似,也是用于生成键值对的集合。
WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名。WeakMap键名所引用的对象都是弱引用,即垃圾回收机制不将该引用考虑在内。
本文不多介绍weakMap相关内容,详情可以看这里。
业务场景介绍
在常见的CRUD业务中,数据枚举值是比较常见的,比如说数据的状态字段。举个栗子:
<template>
<el-table border height="100%" :data="tableData">
<el-table-column label="状态" align="center" width="120" show-overflow-tooltip>
<template #default="{row}">
{{ getLabel(row.status, statusList) }}
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
data() {
return {
tableData: [],
statusList: [{
label: '正常',
value: 1
}, {
label: '紧急',
value: 2
}, {
label: '非常紧急',
value: 3
}]
};
},
methods: {
getLabel(status, statusList) {
const statusEnum = statusList.find(item => item.value === status);
return statusEnum?.label || status;
}
}
};
</script>
解释一下枚举数组为什么要设计成这样:是为了Selector组件选择使用,将来把枚举数组放在公共文件里,可以保证数据的唯一性。
大家可以想想看有什么问题。没错,如果状态量枚举比较多、数据量比较大的话,最多会执行一个N*M的循环嵌套,所以我们可以着手从这里进行优化。
优化第一步:冻结枚举数组
枚举数组不需要响应式
data() {
return {
tableData: [],
statusList: Object.freeze([{
label: '正常',
value: 1
}, {
label: '紧急',
value: 2
}, {
label: '非常紧急',
value: 3
}])
};
},
优化第二步:改造getLabel函数
// utils/enum.js
const weakMap = new WeakMap();
function list2Map(list = [], option = {label: 'label', value: 'value'}) {
const {label, value} = option;
// 找到数据桶
let bucket = weakMap.get(list);
if (!bucket) {
bucket = new Map();
weakMap.set(list, bucket);
}
// 找到数据桶里的label-value对应的map
const key = `label:${label},value:${value}`;
if (!bucket.get(key)) {
const map = {};
list.forEach(item => {
map[item[value]] = item[label];
});
bucket.set(key, map);
}
// 返回map
return bucket.get(key);
}
/**
* 通过value返回对应的label值
* @param {*} val
* @param {*[]} list
* @param {{label: string, value: string}} option
* @returns {*}
*/
export function getLabel(val, list = [], option = { label: 'label', value: 'value' }) {
const obj = list2Map(list, option);
return obj[val] || val;
}
然后在对应的页面引入getLabel方法即可。
欢迎大家提出自己的意见,也可以分享自己的优化方案。明天见!