热门标签 | 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的源码,敬请期待。


推荐阅读
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 前端开发工程师必读书籍有哪些值得推荐?我们直接进入代码复杂版式设置,如下所示,先写些标签,源码在这个链接里面:https://codepen.io/Shadid ... [详细]
  • 如何用Matlab快速画出带有3D渲染效果的复杂曲面
    简要地介绍了一下如何用Matlab快速画出带有3D渲染效果的复杂曲面图,包括三维曲面绘制、光线、材质、着色等等控制,以及如何 ... [详细]
  • 本文详细解析了JavaScript中相称性推断的知识点,包括严厉相称和宽松相称的区别,以及范例转换的规则。针对不同类型的范例值,如差别范例值、统一类的原始范例值和统一类的复合范例值,都给出了具体的比较方法。对于宽松相称的情况,也解释了原始范例值和对象之间的比较规则。通过本文的学习,读者可以更好地理解JavaScript中相称性推断的概念和应用。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
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社区 版权所有