3

我想重新实现一个树组件来提高它的性能。我使用了 react-window 中的 FixedSizeList。它的工作相对较好。它甚至可以处理 100,000 个树节点。

我的问题是,我想为树节点的小开口三角形设置动画。以下css负责动画:

.tree-branch::after {
  content: '';
  display: block;
  width: 0;
  height: 0;
  margin-top: 1px;
  margin-left: 23px;
  border-top: 6px solid transparent;
  border-bottom: 6px solid transparent;
  border-left: 6px solid rgba(0, 0, 0, 0.7);
  opacity: 0.7;
  position: absolute;
  top: 0;
  left: -36px;
  transform: rotate(90deg);
  animation-duration: 0.3s;
}

.tree-item-closed::after {
  transform: rotate(0deg);
}

动画不起作用。因为在每次打开和关闭时所有的列表元素 div 都会重新渲染。然后我尝试为列表添加 itemKey 属性以帮助 React 重用 div。

    <List
      className="List"
      height={height}
      itemCount={flattenedData.length}
      itemSize={32}
      width={width}
      itemKey={index => flattenedData[index].id} // key defined
    >
      {Row}
    </List>

它也不起作用。div 不会更新,而是重新渲染整个 div。这个问题有合适的解决方案吗?如何防止重新渲染?

这是整个示例:https ://codesandbox.io/s/a-quick-react-tree-component-based-on-react-window-tyxnm

4

1 回答 1

7

为了防止react-window重新渲染列表中的每个项目,您需要:

  1. 记忆你的行渲染功能
  2. 将该函数移到父函数范围之外
  3. 使用itemDataprop 在父组件和每行渲染函数之间进行通信。

这是这里的 react-window 示例沙箱中使用的策略:https ://codesandbox.io/s/github/bvaughn/react-window/tree/master/website/sandboxes/memoized-list-items

这是使用您的代码的示例: https ://codesandbox.io/s/a-quick-react-tree-component-based-on-react-window-8psp0

可能有一种更简单的方法可以使用useMemo,但我无法弄清楚。

如果您使用 Chrome 开发工具检查 DOM 节点,您会发现当展开一个节点时,不再为整个树重新创建 DOM 节点。这会消除您在选择新节点时看到的闪烁(在 Chrome 中,但在 Firefox 中没有)。

但是还有其他一些因素会阻止您的旋转动画正常工作。在上面链接的 CodeSandbox 示例中,我在border属性上添加了一些动画,以显示某些 CSS 属性的动画是如何工作的,但transformCSS 属性的动画不起作用。我怀疑这个问题与 无关react-window,因此您可能需要单独调试它以找出为什么您的变换没有动画但其他属性动画正常。

于 2019-06-17T23:17:56.560 回答