【问题标题】:Performance issue with react-tether inside item in a react-virtualized list反应虚拟化列表中项目内部的反应系绳的性能问题
【发布时间】:2017-03-10 07:03:18
【问题描述】:

说明

我有一个可能很长的项目列表,在反应虚拟化 VirtualScroll 中呈现。
列表中的每个项目(行)都有相当多的元素,其中一个会打开上下文菜单。我正在尝试使用 react-tether 在 HTML body 上呈现该菜单(这样当项目位于可滚动列表的底部/顶部时它不会隐藏)并保持菜单“卡在”我的项目上用户滚动列表。
我的问题是更新绑定菜单的位置有明显的滞后。

到目前为止我已采取的一些步骤:

  1. 呈现了一个简单的列表,没有VirtualScroll。系留菜单呈现流畅,没有明显的卡顿。这就是我得出的结论,问题出在react-virtualized
  2. 将我的rowRenderer 简化为只有菜单触发器,如recommended here
  3. 在行组件中实现shouldComponentUpdate。这大大提高了感知性能,大大减少了延迟,但仍然很明显。
  4. 检查了 Chrome 开发工具的时间线。我看到Grid.jstether.js 都触发了回流。

库版本:

  • react-virtualized v. 7.24.3(大型项目,尚未准备好升级到 8.x)
  • react-tether v. 0.5.2
  • 反应 v. 15.2.1

工作演示

https://plnkr.co/edit/f7OhCoCXkDsWbyjxhR3f

截图:

【问题讨论】:

  • "检查了 Chrome devtools 的时间线。我看到 Grid.js 和 tether.js 触发了回流。" - 不确定 Tether,但在 react-virtualized v8 中我对上游 detect-element-resize 库进行了 2 个重要的性能优化,防止它进行大量不必要的回流。如果您使用的是AutoSizer,此更改可能会对您有所帮助。 (如果你不是,那么它就无关紧要了。)如果你能与我分享一些代码,我很乐意看看你的问题——即使它只是一个小的 Plnkr。
  • @brianvaughn 感谢您的快速回复。 1. 我不使用AutoSizer,而是使用我们自己的自定义调整大小处理程序。如果是这样,我可能会尝试升级到 8.x 并切换到AutoSizer 2。我会看看我是否可以设置一个可共享的示例。无论如何,隔离问题可能是个好主意
  • @brianvaughn 我用 splunkr 上的工作演示链接更新了我的问题。延迟是可见的。

标签: javascript performance reactjs react-virtualized tether


【解决方案1】:

仅供参考,Plnkr 已损坏。它包含了错误的样式版本(8.x 而不是 7.x)。

修复该问题后,我看到的视觉“滞后”不是我知道如何使用 7.x 版修复的问题。问题是浏览器在不同的线程中管理滚动(这样 JS 不会阻止它并导致 UI 感觉无响应)。通常这并不明显,因为所有 UI 都在一起滚动,但在这种情况下,您的模态框是由 JS 绝对定位的,因此它有时会落后于浏览器的滚动位置。

话虽如此,升级到版本 8 为您提供了门户方法的替代方法,该方法确实解决了问题,如更新后的 plunk 所示:https://plnkr.co/edit/NESPMzDz22JjwFVthve4?p=preview

他们的关键是:

render() {
  const { menuOpen } = this.state;
  const { index, style } = this.props;

  // Make sure open cells are on a higher z-index than others
  if (menuOpen) {
    style.zIndex = 2;
  }

  return (
    <div
      className="row"
      style={style}
    >
      {list[index]}

      {/* Render your button OR menu item here */}
    </div>
  );
}

【讨论】:

  • 感谢您的建议!如果我添加了计算元素相对于其“滚动父级”边缘的位置的功能,并且如果菜单太靠近底部边缘,则垂直翻转菜单,我可以使用您的建议。
  • 我最初采用门户方法的动机是防止菜单被列表的边缘隐藏(具有overflow-y: hidden),因此即使在最后一行下方也可以完全可见。据我了解,tether.js 已优化为通过 JS 在滚动时更新元素的位置。
  • 我不知道有什么方法可以实现您的目标 - (消除任何可能的滚动延迟来源) - 同时使用像 tether.js 使用的门户技术。您可以期望的最好的结果是尽可能优化性能以减少延迟。为此,我鼓励您考虑升级到 react-virtualized v8,因为该版本包含更多性能优化。我理解您对溢出父 List 边缘的担忧。不幸的是,这是我提到的方法的一个限制。它可能不适合您的需求。 ://
  • 我最终在子菜单打开时禁用了滚动。这与本机选择输入的行为一致。您的回答帮助我确认了我所看到的性能问题是无法避免的。谢谢!
  • 使用popper.js,您可以将元素直接放置在可滚动容器内,从而避免所有延迟来源。查看 v1-beta。免责声明,我是图书馆的作者
猜你喜欢
  • 2018-07-27
  • 2017-07-13
  • 1970-01-01
  • 2017-05-18
  • 1970-01-01
  • 2017-09-08
  • 2017-05-05
  • 2021-09-03
  • 1970-01-01
相关资源
最近更新 更多