Vue3 sort 导致 computed 深度递归依赖?

作者站长头像
站长
· 阅读数 6

问题重现:

我在开发的时候,调取后端接口,此时后端会返回 6w 条数据。在前端已经做出使用虚拟列表优化首次加载后,页面白屏时间依旧异常。(现在已经排除虚拟列表的问题)

然后我通过 chrome performance tab 定位到了我们一个排序函数内部的实现中,有这样一个场景,这个函数接受一个 ref 作为参数。(内部和本题无关的逻辑就不列出来了)Vue3  sort 导致 computed 深度递归依赖?

下图是我未作任何处理的时候,直接将接收的 fileList.value 返回。

Vue3  sort 导致 computed 深度递归依赖?computedonTrack 表现正常。Vue3  sort 导致 computed 深度递归依赖?

但是一旦我在计算属性中添加了 sort reverse 等改变原数组的位置方法时就出现了异常。计算属性好像会错误的认为我要深度追踪这个数组的每一个属性的变化,卡顿的时间就出现在了这里。Vue3  sort 导致 computed 深度递归依赖?

问题: 不是很理解其中的原因,不知道哪位阅读过源码的大佬解读一下这样的原因是否正常?解决方法有哪些呢?

回复
1个回答
avatar
test
2024-07-01

两种思路。

第一种是如果你这个原始的 fileList 并不参与渲染,那么你完全可以不把它声明成 ref 的。然后外面也不要使用 computed,而是直接把这个并不 ref 的 fileList 排序后再直接赋值给 sortFileList 就好。大概类似这样:

// 假如是同步的
const { fileList } = useFileList();
const sortFileList = ref(fileList.sort());

// 假如是异步的
const sortFileList = ref([]);
onBeforeMount(async () => {
    const { fileList } = await useFileList();
    sortFileList.value = fileList.sort();
});

第二种是那你就不要尝试修改原数组,因为你这个 fileList 是 ref 的,你改了原数组就又触发 Proxy 钩子了。你可以在 computed 里先 unref 这个 fileList,然后对 unref 的结果使用 toReversed()、toSorted() 这些不会改变原数组的方法来排序,最后再返回排序结果:

const { fileList } = useFileList();
const sortFileList = computed(() => {
    const temp = unref(fileList);
    return temp.toSorted();
});
MDN - Array.prototype.toReversed()MDN - Array.prototype.toSorted()
回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容