当前位置: 首页 > Web前端 > HTML

React解决长列表解决方案(react-virtualized)

时间:2023-04-02 14:06:10 HTML

github地址响应式组件大列表高效渲染利用窗口特性,即在滚动范围内,呈现你给定数据的一小部分,大大减少了渲染组件所需的时间,以及创建的DOM节点数。缺点:如果滑动太快,可能会出现空白的情况。前端经典问题,在JS中操作渲染大量DOM,直接在JS中操作DOM,会导致性能严重下降,所以渲染一长串(即大量DOM)会导致浏览器卡顿严重,甚至可能出现假死状态。(这里插一句题外话,如果不通过JS渲染大量的DOM,是不会出现这个问题的,但是我们很少这样做,有兴趣的同学可以看下面的渲染分析。)主要解决方案针对这个问题如下:几种滚动加载,渐进渲染DOM(分页,一个意思)。使用合理的逻辑将渲染限制为仅显示部分可视区域。是1的变体,写一个异步循环渲染,让浏览器有机会以异步的方式执行其他任务。(React异步渲染可以关注一下。)1、3两种方案都会遇到一个问题。如果DOM结构过大,用户在网页上的操作体验就会出现问题,比如滚动、点击等常用操作。再次操作DOM时,会卡顿。所以我们今天主要讨论的是解决方案2,即前端遇到一些无法通过分页加载的列表。(毕竟有现成的第三方。)先回顾浏览器渲染过程(webkit)HTML和CSS规则,解析处理HTML标签,构建DOM树。处理CSS标记并构建CSSOM(样式规则)树。将DOM和CSSOM合并到渲染树中。根据渲染树布局(Layout)来计算每个节点的几何信息。将每个节点绘制(Painting)到屏幕上注意:RenderTree渲染树不等同于DOMTree,因为有些东西比如Header标签或者display:none不需要放在渲染树中。CSS的RuleTree主要是完成匹配,将CSSRule附加到RenderTree上的每个Element上,也就是DOM节点,也称为Frame。通过RenderTree,浏览器已经可以知道网页中有哪些节点,每个节点的CSS定义,以及它们的隶属关系。然后,计算出每个Frame(也就是每个Element)的位置,也称为layout和reflow过程。这五个步骤不一定一次按顺序完成。如果修改了DOM或者CSSOM,就需要重复上面的过程,这样它才能计算出哪些像素点需要重新渲染到屏幕上。在实际页面中,CSS和JavaScript经常会多次修改DOM和CSSOM。JavaScript:一般来说,我们会使用JavaScript来实现一些视觉上的变化效果。比如制作动画或者给页面添加一些DOM元素。style:计算样式,这个过程就是根据CSS选择器为每个DOM元素匹配对应的CSS样式。在这一步之后,确定应该将哪些CSS样式规则应用于每个DOM元素。Layout:布局,上一步确定了每个DOM元素的样式规则,这一步是具体计算每个DOM元素最终显示在屏幕上的大小和位置。网页中元素的布局是相对的,一个元素布局的变化会引发其他元素布局的变化。例如,一个元素的宽度变化会影响它的子元素的宽度,而它的子元素宽度的变化会继续影响它的孙元素。所以对于浏览器来说,布局过程经常发生。绘画:绘画本质上是填充像素的过程。包括绘制文字、颜色、图像、边框和阴影等,即一个DOM元素的所有视觉效果。通常,此绘制过程是在多个图层上完成的。Composite:渲染层合并。从上一步可以看出,页面中DOM元素的绘制是在多层上进行的。在完成每一层的绘制过程后,浏览器将所有层按逻辑顺序组合成一层显示在屏幕上。这个过程对于有重叠元素的页面尤为重要,因为一旦图层合并顺序错误,元素就会显示异常。这里还涉及到层(GraphicsLayer)的概念,GraphicsLayer层是作为纹理(texture)上传到GPU的,有时候一个页面的渲染就是CPU和GPU共同协作的结果。大体流程图为什么React中渲染大量DOM会导致浏览器卡顿(15.x)?事件触发线程:当事件被触发(鼠标点击、键盘敲击等)时,线程会将事件添加到待处理队列的末尾,等待JS引擎处理。React使用VirtualDOM和diff算法来优化DOM变化,这也意味着React在渲染真实DOM时,所有的VirtualDOM树都在JS内存中。并且React一旦更新不会执行刷新操作,而是比较所有的差异,将它们放在差异队列中,然后一次性执行patch方法进行更新和渲染(长时间)。GUI线程渲染真实DOM时,由于渲染DOM量大,GUI执行时间会很长(页面会出现空白等)。部分API使用ListAutoSizer、CellMeasurer和List(自适应宽高)InfiniteLoader和List(滚动加载)githubDemo地址