热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在React项目中,怎样文雅的优化长列表

  关于较长的列表,比方1000个数组的数据构造,假如想要同时衬着这1000个数据,天生相应的1000个原生dom,我们晓得原生的dom元素是很庞杂的,假如长列表经由过程天生云云多

  关于较长的列表,比方1000个数组的数据构造,假如想要同时衬着这1000个数据,天生相应的1000个原生dom,我们晓得原生的dom元素是很庞杂的,假如长列表经由过程天生云云多的dom元夙来完成,很能够使网页落空相应。

  贯串React中心的就是”virtual dom”,我们一样的能够经由过程用假造列表的体式格局来文雅的优化长列表

  • 原生dom衬着长列表的瑕玷
  • 假造列表优化长列表的道理
  • 经由过程react-virtualized来优化长列表
  • 经由过程react-tiny-virtual-list来优化长列表

本文的原文地点宣布在我的博客中:

https://github.com/forthealll…

迎接star和fork~

本文的用例的代码地点为:

https://github.com/forthealll…

一、原生dom衬着长列表的瑕玷

  起首我们尝试在React项目中,未做任何优化一次性衬着1000个dom,每一个dom包括一个img标签,原生dom自身是很庞杂的对象,加上img标签后。衬着的效果以下图所示:

《在React项目中,怎样文雅的优化长列表》

  能够很明显的看到白屏的时刻很长,由于在React中,不做任何优化,直接衬着这么包括1000个图片的dom节点,纵然React自身用了假造dom,然则在初次衬着的时刻,是实实在在的天生了1000个实在的dom,我们能够检察网页中的实在dom状况,以下所示:

《在React项目中,怎样文雅的优化长列表》

  从上图我们能够看出,是确确实实的天生了1000个实在的dom,进入页面后,须要衬着这1000个dom,因而白屏的时刻很长。

  另外,在直接衬着1000个dom节点的页面,触发转动事宜,也会使得内存用量增添,详细能够以下图所示:

《在React项目中,怎样文雅的优化长列表》

另外同时衬着许多dom节点,也会形成一下几个题目:

  • 轻易失帧,由于衬着很慢,所以没法保持浏览器的帧率,主观上会显得页面卡顿
  • 网页落空相应,事宜等没法实时被触发

  上述的效果都是在PC端展现的,关于特定的挪动装备,直接无优化的衬着长列表所形成的题目会越发的放大。长列表的衬着在挪动端的许多场景会碰到,比方微博,feeds流中等等。合理的优化长列表,能够提拔用户体验。

二、假造列表优化长列表的道理

优化长列表的道理很简朴,基本道理能够一句话归纳综合:

用数组保留一切列表元素的位置,只衬着可视区内的列表元素,当可视区转动时,依据转动的offset大小以及一切列表元素的位置,盘算在可视区应当衬着哪些元素。

详细完成步骤以下所示:

  1. 起首肯定长列表地点父元素的大小,父元素的大小决议了可视区的宽和高
  2. 肯定长列表每一个列表元素的宽和高,同时初始的条件下盘算好长列表每一个元素相关于父元素的位置,并用一个数组来保留一切列表元素的位置信息
  3. 初次衬着时,只展现相关于父元素可视区内的子列表元素,在转动时,依据父元素的转动的offset从新盘算应当在可视区内的子列表元素。如许保证了无论如何转动,实在衬着出的dom节点只要可视区内的列表元素。
  4. 假定可视区内能展现5个子列表元素,实时长列表总共有1000个元素,然则时时刻刻,实在衬着出来的dom节点只要5个。

5.补充申明,这类状况下,父元素平常运用position:relative,子元素的定位平常运用:position:absolute或sticky

经由过程假造列表优化后,一样的显现1000个包括图片的dom,白屏时刻会大大的削减。详细效果以下图所示:

《在React项目中,怎样文雅的优化长列表》

关于比无优化的状况,优化后的假造列表衬着速率提拔很明显。

三、经由过程react-virtualized来优化长列表

社区完成假造列表的React组件许多,较为经常使用的是react-virtualized和react-tiny-virtual-list,前一个较为周全,第二个较为轻量。接下来会分别来引见这俩个React组件库。

1、react-virtualized简介

react-virtualized是一个完成假造列表较为优异的组件库,react-virtualized供应了一些基本组件用于完成假造列表,假造网格,假造表格等等,它们都能够减小不必要的dom衬着。另外还供应了几个高阶组件,能够完成动态子元素高度,以及自动添补可视区等等。

react-virtualized的基本组件包括:

  • Grid:用于优化构建恣意网状的构造,传入一个二维的数组,衬着出类似棋盘的构造。
  • List:List是基于Grid来完成的,然则是一个维的列表,而不是网状。
  • Table:Table也是基于Grid来完成,表格具有牢固的头部,而且能够在垂直方向上转动
  • Masonry:一样能够在程度方向,也能够在垂直方向转动,不同于Grid的是能够自定义每一个元素的大小,或许子元素的大小也能够是动态变化的
  • Collection:类似于瀑布流的情势,一样能够程度和垂直方向转动。

值得注意的是这些基本组件都是继续于React中的PureComponent,因而当state变化的时刻,只会做一个浅比较来肯定从新衬着与否

除了这几个基本组件外,react-virtualized还供应了几个高阶组件,比方ArrowKeyStepper
、AutoSizer、CellMeasurer、InfiniteLoader等,本文详细引见经常使用的AutoSizer、CellMeasurer和InfiniteLoader。

  • AutoSizer:运用于一个子元素的状况,经由过程AutoSizer包括的子元素会依据父元素Resize的变化,自动调治该子元素的可视区的宽度和高度,同时调治的另有该子元素可视区实在衬着的dom元素的数量。
  • CellMeasurer:这个高阶组件能够动态的转变子元素的高度,适用于提早不晓得长列表中每一个子元素高度的状况。
  • InfiniteLoader:这个高阶组件用于Table或许List的无穷转动,适用于转动时异步要求等状况

2、react-virtualized基本组件的运用

下面我们来引见一下经常使用的基本组件Grid、List。

(1)Grid

一切基本组件基本上都是基于Grid组成的,一个简朴的Grid的例子以下:

import { Grid } from 'react-virtualized';
const list = [
['Jony yu', 'Software Engineer', 'Shenzhen', 'CHINA', 'GUANGZHOU'],
['Jony yu', 'Software Engineer', 'Shenzhen', 'CHINA', 'GUANGZHOU'],
['Jony yu', 'Software Engineer', 'Shenzhen', 'CHINA', 'GUANGZHOU'],
['Jony yu', 'Software Engineer', 'Shenzhen', 'CHINA', 'GUANGZHOU'],
['Jony yu', 'Software Engineer', 'Shenzhen', 'CHINA', 'GUANGZHOU'],
['Jony yu', 'Software Engineer', 'Shenzhen', 'CHINA', 'GUANGZHOU']
];
function cellRenderer ({ columnIndex, key, rowIndex, style }) {
return (
key={key}
https://img8.php1.cn/3cdc5/15579/978/f1a5a98c436a29cd.gif" src="https://img8.php1.cn/3cdc5/15579/978/f1a5a98c436a29cd.gif" alt="《在React项目中,怎样文雅的优化长列表》" />

衬着网格也是只衬着可视区的dom节点,有个风趣的现象是转动条的大小,这里Grid做了一个细节优化,只要转动的时刻才会显现转动条,住手转动后会隐蔽转动条。

(2)List

接着来举例申明一下List的运用:

import { List } from 'react-virtualized';
import loremIpsum from "lorem-ipsum"
const rowCount = 1000;
const list = Array(rowCount).fill().map(()=>{
return loremIpsum({
count: 1,
units: 'sentences',
sentenceLowerBound: 3,
sentenceUpperBound: 3
}
})
function rowRenderer ({
key,
index,
isScrolling,
isVisible,
style
}) {
return (
key={key}
300px",width:"200px"}}>
https://img8.php1.cn/3cdc5/15579/978/786b3cb4901e8027.gif" src="https://img8.php1.cn/3cdc5/15579/978/786b3cb4901e8027.gif" alt="《在React项目中,怎样文雅的优化长列表》" />

2、react-virtualized高阶组件的运用

连系List来看看react-virtualized高阶组件的运用。

(1)AutoSizer

起首来看运用不运用AutoSizer的瑕玷,以下图所示,List只能指定牢固的大小,假如其地点的父元素的大小resize了,那末List是不会主动填满父元素的可视区的:

《在React项目中,怎样文雅的优化长列表》

从上图能够看出来,List是没法自动添补父元素的。因而我们这里须要运用AutoSizer。AutoSizer的运用也很简朴,我们只须要在List的基本上:

class TestList extends Component{
render(){
return



{({ height, width }) => (
src="https://img8.php1.cn/3cdc5/15579/978/c8814c46a97a54dd.gif" alt="《在React项目中,怎样文雅的优化长列表》" />

上述能够看出来增添了AutoSizer能够动态的顺应父元素宽度和高度的变化。

然则也存在一个题目:

子元素太长,换行后转变了子元素的高度后没方法顺应,也就是说仅仅经由过程基本的组件List是不支撑子元素的高度动态转变的场景

(2)CellMeasurer

为了处理上述的子元素能够动态变化的题目,我们能够应用高阶组件CellMeasurer:


import { List,AutoSizer,CellMeasurer, CellMeasurerCache} from 'react-virtualized';
const cache = new CellMeasurerCache({ defaultHeight: 30,fixedWidth: true});
function cellRenderer ({ index, key, parent, style }) {
console.log(index)
return (
cache={cache}
columnIndex={0}
key={key}
parent={parent}
rowIndex={index}
>
https://img8.php1.cn/3cdc5/15579/978/32afd9e8e616dde0.gif" src="https://img8.php1.cn/3cdc5/15579/978/32afd9e8e616dde0.gif" alt="《在React项目中,怎样文雅的优化长列表》" />

上图我们看出来,子列表元素的高度能够动态变化,经由过程CellMeasurer能够完成子元素的动态高度。

(3)InfiniteLoader

末了我们来斟酌这类无穷转动的场景,许多状况下我们能够须要分页加载,就是罕见的在可视区内无穷转动的场景。react-virtualized供应了一个高阶组件InfiniteLoader用于完成无穷转动。

InfiniteLoader的运用很简朴,只要按着文档来即可,就是分页的去在家下一页,转动分页所挪用的函数为:

function loadMoreRows ({ startIndex, stopIndex }) {
return new Promise(function(resolve,reject){
resolve()
}).then(function(){
//模仿ajax要求
let temList = Array(10).fill(1).map(()=>{
return loremIpsum({
count: 1,
units: 'sentences',
sentenceLowerBound:3,
sentenceUpperBound:3
})
})
list = list.concat(temList)
})
}

末了的效果以下:

《在React项目中,怎样文雅的优化长列表》

看起来跟基本组件List一样,实在唯一的区分就是会在转动的时刻自动实行loadMoreRows函数去更新list

(4)总结

经由过程基本组件Grid、List以及高阶组件AutoSizer、CellMeasurer和InfiniteLoader,已能够构建出比较庞杂的场景,然则有一个瑕玷,就是CellMeasurer虽然说肯定程度上支撑动态子元素的高度的变化,实际上是一种预算,存在许多边境状况,没法顺应于动态元素的场景,特别是文本节点较多致使的高度变化。然则关于图片节点的动态高度支撑没有很大的题目。

举例一种边境状况,CellMeasurer没法支撑文本动态高度的状况:

《在React项目中,怎样文雅的优化长列表》

从上图能够看到,逐步减少的过程当中,假如缩的太小,并没有动态的撑大子元素的高度,涌现了笔墨的堆叠。

四、经由过程react-tiny-virtual-list来优化长列表

react-tiny-virtual-list是一个较为轻量的完成假造列表的组件,不同于react-virtualized支撑网格以及表格等衬着优化。
react-tiny-virtual-list只支撑列表,运用方便,其源码也只要700多行。

运用极为简朴:

import VirtualList from 'react-tiny-virtual-list';
const data = ['A', 'B', 'C', 'D', 'E', 'F','A', 'B', 'C',
'D', 'E', 'F','A', 'B', 'C', 'D', 'E', 'F',
'A', 'B', 'C', 'D', 'E', 'F'];
export default class TinyVirtual extends Component {
render(){
return
height={200}
itemCount={data.length}
itemSize={50} // Also supports variable heights (array or function getter)
renderItem={({index, style}) =>


}
/>
}
}

末了的衬着效果也是类似的,也能够支撑无穷转动等等。

然则react-tiny-virtual-list有一个致命的瑕玷:

完整不支撑子元素的动态高度或许宽度

五、总结

本文引见了假造列表的优化的道理,以及经常使用的React能够优化假造列表的组件库。在接下来的文章中,会详细的引见react-tiny-virtual-list和react-virtualized的源码,敬请期待。


推荐阅读
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Html5-Canvas实现简易的抽奖转盘效果
    本文介绍了如何使用Html5和Canvas标签来实现简易的抽奖转盘效果,同时使用了jQueryRotate.js旋转插件。文章中给出了主要的html和css代码,并展示了实现的基本效果。 ... [详细]
  • 本文总结了在编写JS代码时,不同浏览器间的兼容性差异,并提供了相应的解决方法。其中包括阻止默认事件的代码示例和猎取兄弟节点的函数。这些方法可以帮助开发者在不同浏览器上实现一致的功能。 ... [详细]
  • 本文介绍了Python字典视图对象的示例和用法。通过对示例代码的解释,展示了字典视图对象的基本操作和特点。字典视图对象可以通过迭代或转换为列表来获取字典的键或值。同时,字典视图对象也是动态的,可以反映字典的变化。通过学习字典视图对象的用法,可以更好地理解和处理字典数据。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • React基础篇一 - JSX语法扩展与使用
    本文介绍了React基础篇一中的JSX语法扩展与使用。JSX是一种JavaScript的语法扩展,用于描述React中的用户界面。文章详细介绍了在JSX中使用表达式的方法,并给出了一个示例代码。最后,提到了JSX在编译后会被转化为普通的JavaScript对象。 ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
author-avatar
最好的冥羽
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有