sorrycc / weekly

MDH Weekly 前端周刊,每周一上午 9 点发布。
https://mdhweekly.com/
1.1k stars 44 forks source link

自荐: 高性能的React表格组件 #25

Closed jhoneybee closed 3 years ago

jhoneybee commented 3 years ago

项目地址: https://github.com/HighPerformanceComponent/rc-grid

最佳的表格优化体验

通过开发rc-grid 表格,得到一下的优化经验,分享给大家,解决其他类似的问题

关于表格白屏, 也就是滚动的时候闪烁的问题。

在 sorrycc 的一篇最佳表格里面曾经提到过这样一个优化表格白屏幕的技巧。地址我依稀不清楚了,但是我内容我大概记得。 通过自定义滚动条, onwheel 来控制滚动逻辑。

很好奇,为什么 onwheel 可以去解决闪烁的问题?

后来通过搜索资料我才发现了一个关键的属性 will-change: transform; 可以优化滚动效率, 在通过检索资料后来我才发现一个有趣的事情。

浏览器在优化滚动效率的时候,会有这样两个线程来进行处理

  1. onScroll 事件是独立在一个线程中(也可能是在一个进程中)
  2. render 也就是渲染 div 的时候是独立的

这么优化的原因可能是因为,浏览器为了解决滚动的流畅问题。 将 onScroll 和 render 分开 ,这样不会影响到页面的流畅程度。 但是由于在 滚动的时候调用 setState/ useState 的时候会发现滚动的 render 线程异步没即时的执行。也就是说在 onScroll 中不一定等待render执行完成,才会执行下次的 onScroll 特别是在firefox 浏览器中异常明显。 因为firefox默认优化就是不同步的。而在webkit引擎中,似乎只有设置过 will-change 才会滚动异步。

知道产生白屏的原因以后,我们就知道如何解决了。 将 render 控制在自己的范围内,例如不使用浏览器的 onScroll, 而是通过 onwheel 来实现。 但是这样得不到 未来浏览器的关于滚动的fps 优化。同样也得不到现在目前浏览器带来的 “白屏的问题”

如果是在基于 webkit 浏览器中,同样 取消 will-change 这样也会同步render不会闪动,但是这个在 firefox 中无效。

例如我们取消 https://react-window.vercel.app/#/examples/list/fixed-size 例子中的 will-change 属性,同样滚动起来非常棒

关于表格的固定列, 固定表头

css 中的 position: sticky 是一个很棒的属性, 用来固定非常不错, 如果想要获得更好的浏览器支持,一般建议,表头和body分开, 通过事件,统一的同步滚动,但是这样会在低端的硬件情况下带来细微的滚动不同步的视觉效果。 position: sticky 带来的视觉效果,和性能都很棒,但是部分浏览器不支持。

关于是否使用 react-window or 自己实现虚拟滚动

建议自己实现虚拟滚动,虽然 react-window 非常棒,也开箱即用,但是在设置行点击,或则行样式的问题情况下, react-window 中的 只有 cell 没有 row 一些很好实现的功能点,在 react-window 中反而实现起来比较复杂了。 所以建议自己实现虚拟滚动方便优化性能

关于调试表格的性能问题

我比较常用的方式就是,可以打开浏览器的fps ,在控制台上输入 show fps 这样可以看到是在什么情况下导致的性能降低, 或则用 performance 来进行性能瓶颈的详细问题。 render 还是 脚本执行的时间。甚至在 performance 中还可以看到具体存在问题的具体行

!!! 优化到最后,其实总结经验无非就一条 “少即是快”, 越少的 dom元素,越少的循环次数那么执行的效率就越高(不过这是废话,但也是我体验最深刻的一句话)!!!