我如何重构这个Vue检查树组合以提高性能

ljo96ir5  于 2023-05-01  发布在  Vue.js
关注(0)|答案(1)|浏览(168)

目前,我正在尝试使一个Vue 3组合,使无头递归复选框树视图。校验树只选择叶节点,内部节点的状态总是基于选择了多少个叶节点。
https://stackblitz.com/edit/vitejs-vite-leu5hm?file=src%2FdataItems.ts,src%2FCheckTree.vue,src%2FCollapseItem.vue,src%2FuseCheckTree.ts,src%2FApp.vue
然而,我遇到的问题是,当检查一个项目时,性能可能会非常慢,特别是在开发模式下(很容易3秒选择1复选框)。在stackblitz示例中,我添加了100行,每行包含大约35个子行数据。正如您所看到的,当用户选中一个框时,整个转换后的数据将再次循环。这个递归循环本身是相当严重的性能损失,以及组件的后续重渲染。
有没有办法让这更有效率?我真的很感激任何输入。😇🙏

bfrts1fy

bfrts1fy1#

摆脱所有的破坏操作,特别是在循环中。看起来你也可以避免很多转换。这里有一个例子,你的getCheckedTriState()
在这里,您从leafNodes数组递归地构建对象,然后创建一个新对象来覆盖某些属性的值,然后仅从具有true值的条目构建一个数组:

function getCheckedTriState(leafNodes: TDataItem[]) {
  const totalLeafNodeIds = leafNodes.reduce((key, value) => ({ ...key, [value.id]: false }), {});
  const allNodes = { ...totalLeafNodeIds, ...internalCheckedModel.value };
  const unCheckedLeafNodes = Object.entries(allNodes).filter(([_, value]) => value === false).map(([key]) => key);

  if (unCheckedLeafNodes.length === 0) return true; // checked
  if (unCheckedLeafNodes.length === Object.keys(totalLeafNodeIds).length) return false; // unchecked
    return null; // indeterminate
};

但您可以只计算所选叶的数量,并将其与可用叶的数量进行比较:

function getCheckedTriState(leafNodes: TDataItem[]) {
  const countUnchecked = leafNodes.reduce((countUnchecked, dataItem) => 
    !internalCheckedModel.value[dataItem.id] ? countUnchecked+1 : countUnchecked
  , 0)

  if (countUnchecked === 0) return true; // checked
  if (countUnchecked === leafNodes.length) return false; // unchecked
    return null; // indeterminate
};

或者更简单:

function getCheckedTriState(leafNodes: TDataItem[]) {
  if (leafNodes.length === 0) return false
  const firstIsChecked = internalCheckedModel.value[leafNodes[0].id]
  const nodesHaveSameState = leafNodes.every(node => internalCheckedModel.value[node.id] === firstIsChecked)
  return nodesHaveSameState ? firstIsChecked : null;
}

请注意,我正在重新设计您的代码,我可能会错过有关您的数据结构的细节。例如,我假设internalCheckedModel不包含不是leafNodes中id的键,并且internalCheckedModel的值都是布尔值。如果这是不准确的,你将不得不进行相应的调整。
最后,无论如何,你都必须自己修复你的代码,我希望通过比较这三个函数能给予你知道要寻找什么。
如果你想减少重新渲染的次数,可以看看v-memo指令,我认为文档中的示例非常接近你所需要的。

相关问题