国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

在React項(xiàng)目中,如何優(yōu)雅的優(yōu)化長(zhǎng)列表

Java_oldboy / 2429人閱讀

摘要:合理的優(yōu)化長(zhǎng)列表,可以提升用戶體驗(yàn)。這樣保證了無(wú)論如何滾動(dòng),真實(shí)渲染出的節(jié)點(diǎn)只有可視區(qū)內(nèi)的列表元素。具體效果如下圖所示對(duì)于比無(wú)優(yōu)化的情況,優(yōu)化后的虛擬列表渲染速度提升很明顯。是基于來(lái)實(shí)現(xiàn)的,但是是一個(gè)維的列表,而不是網(wǎng)狀。

??對(duì)于較長(zhǎng)的列表,比如1000個(gè)數(shù)組的數(shù)據(jù)結(jié)構(gòu),如果想要同時(shí)渲染這1000個(gè)數(shù)據(jù),生成相應(yīng)的1000個(gè)原生dom,我們知道原生的dom元素是很復(fù)雜的,如果長(zhǎng)列表通過(guò)生成如此多的dom元素來(lái)實(shí)現(xiàn),很可能使網(wǎng)頁(yè)失去響應(yīng)。

??貫穿React核心的就是"virtual dom",我們同樣的可以通過(guò)用虛擬列表的方式來(lái)優(yōu)雅的優(yōu)化長(zhǎng)列表

原生dom渲染長(zhǎng)列表的缺陷

虛擬列表優(yōu)化長(zhǎng)列表的原理

通過(guò)react-virtualized來(lái)優(yōu)化長(zhǎng)列表

通過(guò)react-tiny-virtual-list來(lái)優(yōu)化長(zhǎng)列表

本文的原文地址發(fā)布在我的博客中:

https://github.com/forthealll...

歡迎star和fork~

本文的用例的代碼地址為:

https://github.com/forthealll...

一、原生dom渲染長(zhǎng)列表的缺陷

??首先我們嘗試在React項(xiàng)目中,未做任何優(yōu)化一次性渲染1000個(gè)dom,每個(gè)dom包含一個(gè)img標(biāo)簽,原生dom本身是很復(fù)雜的對(duì)象,加上img標(biāo)簽后。渲染的效果如下圖所示:

??可以很明顯的看到白屏的時(shí)間很長(zhǎng),因?yàn)樵赗eact中,不做任何優(yōu)化,直接渲染這么包含1000個(gè)圖片的dom節(jié)點(diǎn),即使React本身用了虛擬dom,但是在首次渲染的時(shí)候,是實(shí)實(shí)在在的生成了1000個(gè)真實(shí)的dom,我們可以查看網(wǎng)頁(yè)中的真實(shí)dom情況,如下所示:

??從上圖我們可以看出,是確確實(shí)實(shí)的生成了1000個(gè)真實(shí)的dom,進(jìn)入頁(yè)面后,需要渲染這1000個(gè)dom,因此白屏的時(shí)間很長(zhǎng)。

??此外,在直接渲染1000個(gè)dom節(jié)點(diǎn)的頁(yè)面,觸發(fā)滾動(dòng)事件,也會(huì)使得內(nèi)存用量增加,具體可以如下圖所示:

此外同時(shí)渲染很多dom節(jié)點(diǎn),也會(huì)造成一下幾個(gè)問(wèn)題:

容易失幀,因?yàn)殇秩竞苈詿o(wú)法維持瀏覽器的幀率,主觀上會(huì)顯得頁(yè)面卡頓

網(wǎng)頁(yè)失去響應(yīng),事件等無(wú)法及時(shí)被觸發(fā)

??上述的效果都是在PC端展示的,對(duì)于特定的移動(dòng)設(shè)備,直接無(wú)優(yōu)化的渲染長(zhǎng)列表所造成的問(wèn)題會(huì)更加的放大。長(zhǎng)列表的渲染在移動(dòng)端的很多場(chǎng)景會(huì)遇到,比如微博,feeds流中等等。合理的優(yōu)化長(zhǎng)列表,可以提升用戶體驗(yàn)。

二、虛擬列表優(yōu)化長(zhǎng)列表的原理

優(yōu)化長(zhǎng)列表的原理很簡(jiǎn)單,基本原理可以一句話概括:

用數(shù)組保存所有列表元素的位置,只渲染可視區(qū)內(nèi)的列表元素,當(dāng)可視區(qū)滾動(dòng)時(shí),根據(jù)滾動(dòng)的offset大小以及所有列表元素的位置,計(jì)算在可視區(qū)應(yīng)該渲染哪些元素。

具體實(shí)現(xiàn)步驟如下所示:

首先確定長(zhǎng)列表所在父元素的大小,父元素的大小決定了可視區(qū)的寬和高

確定長(zhǎng)列表每一個(gè)列表元素的寬和高,同時(shí)初始的條件下計(jì)算好長(zhǎng)列表每一個(gè)元素相對(duì)于父元素的位置,并用一個(gè)數(shù)組來(lái)保存所有列表元素的位置信息

首次渲染時(shí),只展示相對(duì)于父元素可視區(qū)內(nèi)的子列表元素,在滾動(dòng)時(shí),根據(jù)父元素的滾動(dòng)的offset重新計(jì)算應(yīng)該在可視區(qū)內(nèi)的子列表元素。這樣保證了無(wú)論如何滾動(dòng),真實(shí)渲染出的dom節(jié)點(diǎn)只有可視區(qū)內(nèi)的列表元素。

假設(shè)可視區(qū)內(nèi)能展示5個(gè)子列表元素,及時(shí)長(zhǎng)列表總共有1000個(gè)元素,但是每時(shí)每刻,真實(shí)渲染出來(lái)的dom節(jié)點(diǎn)只有5個(gè)。

5.補(bǔ)充說(shuō)明,這種情況下,父元素一般使用position:relative,子元素的定位一般使用:position:absolute或sticky

通過(guò)虛擬列表優(yōu)化后,同樣的顯示1000個(gè)包含圖片的dom,白屏?xí)r間會(huì)大大的減少。具體效果如下圖所示:

對(duì)于比無(wú)優(yōu)化的情況,優(yōu)化后的虛擬列表渲染速度提升很明顯。

三、通過(guò)react-virtualized來(lái)優(yōu)化長(zhǎng)列表

社區(qū)實(shí)現(xiàn)虛擬列表的React組件很多,較為常用的是react-virtualized和react-tiny-virtual-list,前一個(gè)較為全面,第二個(gè)較為輕量。接下來(lái)會(huì)分別來(lái)介紹這倆個(gè)React組件庫(kù)。

1、react-virtualized簡(jiǎn)介

react-virtualized是一個(gè)實(shí)現(xiàn)虛擬列表較為優(yōu)秀的組件庫(kù),react-virtualized提供了一些基礎(chǔ)組件用于實(shí)現(xiàn)虛擬列表,虛擬網(wǎng)格,虛擬表格等等,它們都可以減小不必要的dom渲染。此外還提供了幾個(gè)高階組件,可以實(shí)現(xiàn)動(dòng)態(tài)子元素高度,以及自動(dòng)填充可視區(qū)等等。

react-virtualized的基礎(chǔ)組件包含:

Grid:用于優(yōu)化構(gòu)建任意網(wǎng)狀的結(jié)構(gòu),傳入一個(gè)二維的數(shù)組,渲染出類(lèi)似棋盤(pán)的結(jié)構(gòu)。

List:List是基于Grid來(lái)實(shí)現(xiàn)的,但是是一個(gè)維的列表,而不是網(wǎng)狀。

Table:Table也是基于Grid來(lái)實(shí)現(xiàn),表格具有固定的頭部,并且可以在垂直方向上滾動(dòng)

Masonry:同樣可以在水平方向,也可以在垂直方向滾動(dòng),不同于Grid的是可以自定義每個(gè)元素的大小,或者子元素的大小也可以是動(dòng)態(tài)變化的

Collection:類(lèi)似于瀑布流的形式,同樣可以水平和垂直方向滾動(dòng)。

值得注意的是這些基礎(chǔ)組件都是繼承于React中的PureComponent,因此當(dāng)state變化的時(shí)候,只會(huì)做一個(gè)淺比較來(lái)確定重新渲染與否

除了這幾個(gè)基礎(chǔ)組件外,react-virtualized還提供了幾個(gè)高階組件,比如ArrowKeyStepper
、AutoSizer、CellMeasurer、InfiniteLoader等,本文具體介紹常用的AutoSizer、CellMeasurer和InfiniteLoader。

AutoSizer:使用于一個(gè)子元素的情況,通過(guò)AutoSizer包含的子元素會(huì)根據(jù)父元素Resize的變化,自動(dòng)調(diào)節(jié)該子元素的可視區(qū)的寬度和高度,同時(shí)調(diào)節(jié)的還有該子元素可視區(qū)真實(shí)渲染的dom元素的數(shù)目。

CellMeasurer:這個(gè)高階組件可以動(dòng)態(tài)的改變子元素的高度,適用于提前不知道長(zhǎng)列表中每一個(gè)子元素高度的情況。

InfiniteLoader:這個(gè)高階組件用于Table或者List的無(wú)限滾動(dòng),適用于滾動(dòng)時(shí)異步請(qǐng)求等情況

2、react-virtualized基礎(chǔ)組件的使用

下面我們來(lái)介紹一下常用的基礎(chǔ)組件Grid、List。

(1)Grid

所有基礎(chǔ)組件基本上都是基于Grid構(gòu)成的,一個(gè)簡(jiǎn)單的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 (
    
{list[rowIndex][columnIndex]}
) } render( , rootEl );

顯示的效果如下圖所示:

渲染網(wǎng)格也是只渲染可視區(qū)的dom節(jié)點(diǎn),有個(gè)有趣的現(xiàn)象是滾動(dòng)條的大小,這里Grid做了一個(gè)細(xì)節(jié)優(yōu)化,只有滾動(dòng)的時(shí)候才會(huì)顯示滾動(dòng)條,停止?jié)L動(dòng)后會(huì)隱藏滾動(dòng)條。

(2)List

接著來(lái)舉例說(shuō)明一下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 (
    
{list[index]}
) } export default class TestList extends Component{ render(){ return
} }

List的使用方法也是極簡(jiǎn),指定列表總條數(shù)rowCount,每一條的高度rowHeight以及每次渲染的函數(shù)rowRenderer,就可以構(gòu)建一個(gè)渲染列表。具體的效果如下圖所示:

2、react-virtualized高階組件的使用

結(jié)合List來(lái)看看react-virtualized高階組件的使用。

(1)AutoSizer

首先來(lái)看使用不使用AutoSizer的缺點(diǎn),如下圖所示,List只能指定固定的大小,如果其所在的父元素的大小resize了,那么List是不會(huì)主動(dòng)填滿父元素的可視區(qū)的:

從上圖可以看出來(lái),List是無(wú)法自動(dòng)填充父元素的。因此我們這里需要使用AutoSizer。AutoSizer的使用也很簡(jiǎn)單,我們只需要在List的基礎(chǔ)上:

class TestList extends Component{
  render(){
    return 
{({ height, width }) => ( )}
} }

效果如下圖所示:

上述可以看出來(lái)增加了AutoSizer可以動(dòng)態(tài)的適應(yīng)父元素寬度和高度的變化。

但是也存在一個(gè)問(wèn)題:

子元素太長(zhǎng),換行后改變了子元素的高度后無(wú)法子適應(yīng),也就是說(shuō)僅僅通過(guò)基礎(chǔ)的組件List是不支持子元素的高度動(dòng)態(tài)改變的場(chǎng)景

(2)CellMeasurer

為了解決上述的子元素可以動(dòng)態(tài)變化的問(wèn)題,我們可以利用高階組件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 (
    
      
{list[index]}
); }

對(duì)于需要渲染的List,如下所示:

class TestList extends Component{
  render(){
    return 
{({ height, width }) => ( )}
} }

最后的結(jié)果如下所示:

上圖我們看出來(lái),子列表元素的高度可以動(dòng)態(tài)變化,通過(guò)CellMeasurer可以實(shí)現(xiàn)子元素的動(dòng)態(tài)高度。

(3)InfiniteLoader

最后我們來(lái)考慮這種無(wú)限滾動(dòng)的場(chǎng)景,很多情況下我們可能需要分頁(yè)加載,就是常見(jiàn)的在可視區(qū)內(nèi)無(wú)限滾動(dòng)的場(chǎng)景。react-virtualized提供了一個(gè)高階組件InfiniteLoader用于實(shí)現(xiàn)無(wú)限滾動(dòng)。

InfiniteLoader的使用很簡(jiǎn)單,只要按著文檔來(lái)即可,就是分頁(yè)的去在家下一頁(yè),滾動(dòng)分頁(yè)所調(diào)用的函數(shù)為:

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

最后的效果如下:

看起來(lái)跟基礎(chǔ)組件List一樣,其實(shí)唯一的區(qū)別就是會(huì)在滾動(dòng)的時(shí)候自動(dòng)執(zhí)行l(wèi)oadMoreRows函數(shù)去更新list

(4)總結(jié)

通過(guò)基礎(chǔ)組件Grid、List以及高階組件AutoSizer、CellMeasurer和InfiniteLoader,已經(jīng)可以構(gòu)建出比較復(fù)雜的場(chǎng)景,但是有一個(gè)缺陷,就是CellMeasurer雖說(shuō)一定程度上支持動(dòng)態(tài)子元素的高度的變化,其實(shí)是一種估算,存在很多邊界情況,無(wú)法適應(yīng)于動(dòng)態(tài)元素的場(chǎng)景,特別是文本節(jié)點(diǎn)較多導(dǎo)致的高度變化。但是對(duì)于圖片節(jié)點(diǎn)的動(dòng)態(tài)高度支持沒(méi)有很大的問(wèn)題。

舉例一種邊界情況,CellMeasurer無(wú)法支持文本動(dòng)態(tài)高度的情況:

從上圖可以看到,慢慢縮小的過(guò)程中,如果縮的太小,并沒(méi)有動(dòng)態(tài)的撐大子元素的高度,出現(xiàn)了文字的重疊。

四、通過(guò)react-tiny-virtual-list來(lái)優(yōu)化長(zhǎng)列表

react-tiny-virtual-list是一個(gè)較為輕量的實(shí)現(xiàn)虛擬列表的組件,不同于react-virtualized支持網(wǎng)格以及表格等渲染優(yōu)化。
react-tiny-virtual-list只支持列表,使用方便,其源碼也只有700多行。

使用極其簡(jiǎn)單:

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 
              
// The style property contains the item"s absolute position Letter: {data[index]}, Row: #{index}
} /> } }

最后的渲染結(jié)果也是相似的,也可以支持無(wú)限滾動(dòng)等等。

但是react-tiny-virtual-list有一個(gè)致命的缺點(diǎn):

完全不支持子元素的動(dòng)態(tài)高度或者寬度

五、總結(jié)

本文介紹了虛擬列表的優(yōu)化的原理,以及常用的React可以優(yōu)化虛擬列表的組件庫(kù)。在接下來(lái)的文章中,會(huì)具體的介紹react-tiny-virtual-list和react-virtualized的源碼,敬請(qǐng)期待。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/114347.html

相關(guān)文章

  • React項(xiàng)目如何優(yōu)雅優(yōu)化長(zhǎng)列表

    摘要:合理的優(yōu)化長(zhǎng)列表,可以提升用戶體驗(yàn)。這樣保證了無(wú)論如何滾動(dòng),真實(shí)渲染出的節(jié)點(diǎn)只有可視區(qū)內(nèi)的列表元素。具體效果如下圖所示對(duì)于比無(wú)優(yōu)化的情況,優(yōu)化后的虛擬列表渲染速度提升很明顯。是基于來(lái)實(shí)現(xiàn)的,但是是一個(gè)維的列表,而不是網(wǎng)狀。 ??對(duì)于較長(zhǎng)的列表,比如1000個(gè)數(shù)組的數(shù)據(jù)結(jié)構(gòu),如果想要同時(shí)渲染這1000個(gè)數(shù)據(jù),生成相應(yīng)的1000個(gè)原生dom,我們知道原生的dom元素是很復(fù)雜的,如果長(zhǎng)列表...

    yearsj 評(píng)論0 收藏0
  • 前端面試題總結(jié)(js、html、小程序、React、ES6、Vue、算法、全棧熱門(mén)視頻資源)

    摘要:并總結(jié)經(jīng)典面試題集各種算法和插件前端視頻源碼資源于一身的文檔,優(yōu)化項(xiàng)目,在瀏覽器端的層面上提升速度,幫助初中級(jí)前端工程師快速搭建項(xiàng)目。 本文是關(guān)注微信小程序的開(kāi)發(fā)和面試問(wèn)題,由基礎(chǔ)到困難循序漸進(jìn),適合面試和開(kāi)發(fā)小程序。并總結(jié)vue React html css js 經(jīng)典面試題 集各種算法和插件、前端視頻源碼資源于一身的文檔,優(yōu)化項(xiàng)目,在瀏覽器端的層面上提升速度,幫助初中級(jí)前端工程師快...

    pumpkin9 評(píng)論0 收藏0
  • 前端面試題總結(jié)(js、html、小程序、React、ES6、Vue、算法、全棧熱門(mén)視頻資源)

    摘要:并總結(jié)經(jīng)典面試題集各種算法和插件前端視頻源碼資源于一身的文檔,優(yōu)化項(xiàng)目,在瀏覽器端的層面上提升速度,幫助初中級(jí)前端工程師快速搭建項(xiàng)目。 本文是關(guān)注微信小程序的開(kāi)發(fā)和面試問(wèn)題,由基礎(chǔ)到困難循序漸進(jìn),適合面試和開(kāi)發(fā)小程序。并總結(jié)vue React html css js 經(jīng)典面試題 集各種算法和插件、前端視頻源碼資源于一身的文檔,優(yōu)化項(xiàng)目,在瀏覽器端的層面上提升速度,幫助初中級(jí)前端工程師快...

    Carson 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<