最近做的一个项目中有一个全选的功能,类似于相册中的功能。数据量超万。一开始用的elementplus组件库中的 Checkbox 多选框,但是我发现要是数量达到几千的时候,页面已经就很卡顿了。
有人肯定说,是不是页面的节点太多了导致的。我已经使用了虚拟列表了,页面上也就渲染了十几个节点,就是很卡顿。
我猜elementplus的Checkbox 多选框应该是用js数组提供的方法来判断的,我问了aiArray.includes(value)的时间复杂度是O(n)。所以当数量多的时候遍历时间就成指数上涨
知道问题就会好办很多,于是我就发现了new Set(),
new Set()
关于介绍大家自行网上搜索即可。我这里主要说的是new Set()底层的话用的是哈希表。它的时间复杂度是O(1),并且提供了一个has()方法来判断一个元素是否存在里面。
于是就不用el-checkbox-group直接用el-checkbox,为什么要说这个组件呢,因为这里也是有坑的。就是el-checkbox不和el-checkbox-group一起用的话就没办法用:value属性,于是我就看api中还有个checked属性,谁知道这个也是个坑,只有初始化的时候生效,数据变化时不生效。于是只能自己写了个checkbox,自己写也不难。
正式进入第二个问题
那就是在vue中用new Set()作用响应数据的话,vue捕获不到new Set()的数据变化,因为new Set()添加数据用new Set().add(value),删除用的是new Set().delete(value)vue无法捕获到数据更新。主要就是vue的数据代理。
这里分享两个解决思路:
重新赋值
const checkedIdSet = ref(new Set())
function toggleCheck(id: number, checked: boolean) {
if (checked) {
checkedIdSet.value.add(id)
} else {
checkedIdSet.value.delete(id)
}
checkedIdSet.value = new Set(checkedIdSet.value) //重新赋值促触发vue派发更新
}
给组件绑定key
<template>
<div
:key="refresh"
v-show="isMultipleSelection"
class="checkbox-mask"
@click="toggleCheck(item.id, !checkedIdSet.has(item.id))"
>
<div class="point" :class="{ active: checkedIdSet.has(item.id) }"></div>
</div>
</template>
<script>
const refresh = ref(0)
const checkedIdSet = ref(new Set())
function toggleCheck(id: number, checked: boolean) {
if (checked) {
checkedIdSet.value.add(id)
} else {
checkedIdSet.value.delete(id)
}
refresh.value += 1 //重新赋值促触发vue派发更新
}
</script>
用new Set()后即使是上万条数据页面没有卡顿了