优化之new Set()的妙用

125 阅读2分钟

最近做的一个项目中有一个全选的功能,类似于相册中的功能。数据量超万。一开始用的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()后即使是上万条数据页面没有卡顿了

有其他的方法的在评论中留言