高级套娃之react-virtualized建议收藏

高级套娃react-virtualized

目录

    • 高级套娃react-virtualized
      • 概述
      • 基本使用
        • list
        • AutoSizer
        • WindowScroller
        • InfiniteLoader
      • 结尾

概述

  • 可以解决页面中长列表的渲染,实现在动态在可视区域加载内容
  • react-virtualized 是React组件,用来高效渲染大型列表和表格数据
  • GitHub地址: react-virtualized

基本使用

npm install react-virtualized --save
// 安装该组件

  • 之后在项目中导入便可
    • import { } from ‘react-virtualized’

list

  • GitHub地址:list

  • 基本使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
      <List
        autoHeight
        <!-- 组件的宽度 -->
        width={width}
        <!-- 组件的高度 -->
        height={height}
        <!-- 每一行的数量 -->
        rowCount={count}
        <!-- 每行的高度 -->
        rowHeight={120}
        <!-- 渲染每一行的内容 -->
        rowRenderer={this.rowRenderer}
      />
        <!-- 渲染每一行的内容 -->
        rowRenderer({
          key,         // 每一行的唯一标识
          index,       // 索引号
          style        // 重点属性:一定要给每一个行数添加该样式
          isScrolling, // 当前列表是否在滚动中
          isVisible,   //这一行是否在列表中可见
          }) {
            return (
              <div key={key} style={style}>
                {list[index]}
              </div>
            );
        }

  • 这样使用后虽然可以实现长列表的展示,但是因为高度无法确定所以我们需要另外的高阶组件来进行包装(AutoSizer),并且list组件的滚动条和屏幕的滚动条并不是同一个,所以我们还需要用(WindowScroller)高阶组件来包装list组件

AutoSizer

  • GitHub地址:AutoSizer
  • 基本使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <AutoSizer>
    <!-- 这个宽度将会自适应屏幕宽度 -->
    {({width}) => (
      <List
       <!-- 省略其他代码 -->
       width={width}
       />
    )}
    </AutoSizer>
  • 这样使用后list 组件将会自适应屏幕宽度,虽然这个组件也能提供自适应高度,但是list组件如果需要滚动,也不能使用AutoSizer组件提供的高度,虽然可以自适应屏幕高度,但这样list组件的高度将被固定

WindowScroller

  • GitHub地址:WindowScroller
  • 基本使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
      <WindowScroller>
      <!-- 高度、是否正在滚动、滚动条 -->
      {({ height, isScrolling, scrollTop }) => (
        <AutoSizer>
          {({width}) => (
              <List
                autoHeight
                height={height}
                isScrolling={isScrolling}
                rowCount={...}
                rowHeight={...}
                rowRenderer={...}
                scrollTop={scrollTop}
                width={...}
              />
            />
          )}
        </AutoSizer>
      )}
    </WindowScroller>
  • 这样使用后虽然可以基本实现list组件的滚动、宽度高度都自适应屏幕,但是这样并不是动态的在可视区域渲染数据,我们需用利用最后一个高阶组件(InfiniteLoader)来进行最后的包装

InfiniteLoader

  • GitHub地址:InfiniteLoader

  • 基本使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
      <InfiniteLoader
      <!-- 数据是否在滚动 -->
      isRowLoaded={isRowLoaded}
      <!-- 加载更多的数据,当数据快要被滚动完毕时执行 -->
      loadMoreRows={loadMoreRows}
      <!-- 数据总条数 -->
      rowCount={remoteRowCount}
      >
      <!-- onRowsRendered表示是否滚动完毕 -->
      <!-- registerChild 用来注册List组件 -->
      {({ onRowsRendered, registerChild }) => (
       <WindowScroller>
      <!-- 高度、是否正在滚动、滚动条 -->
        {({ height, isScrolling, scrollTop }) => (
        <AutoSizer>
          {({width}) => (
              <List
                ref={registerChild}
                autoHeight
                height={height}
                isScrolling={isScrolling}
                rowCount={...}
                rowHeight={...}
                rowRenderer={...}
                scrollTop={scrollTop}
                width={width}
                onRowsRendered={onRowsRendered}
              />
            />
          )}
        </AutoSizer>
        )}
        </WindowScroller>
      )}
        </InfiniteLoader>
        <!-- 判断数据是否快要滚动完毕 -->
        function isRowLoaded ({ index }) {
      <!-- 返回一个布尔值 -->
        return !!list[index];
            }
        <!-- 加载更多的数据,每次默认加载十条数据 -->
        <!-- startIndex 开始的索引 -->
        <!-- stopIndex 结束的索引 -->
        function loadMoreRows ({ startIndex, stopIndex }) {
        <!-- 需要返回一个Promise数据 -->
        return fetch(`path/to/api?startIndex=${startIndex}&stopIndex=${stopIndex}`)
            .then(response => {
                <!-- 将响应的数据存储在`state`中 -->
                })
       }
  • 这样基本上可以实现list组件的无限滚动,但是在滚动速度过快时,可能会引起数据加载不过来,导致报错,我们可以在list组件中的rowRenderer渲染每一行的方法中添加一个判断,如果当前数组中的那一项并没有值,可能是因为滚动速度过快引起,所以在当数据没有值时,我们可以先渲染一个占位属性,当数据加载完毕在重新显示

    在这里插入图片描述

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      <!-- 渲染每一行的内容 -->
        rowRenderer({
          key,         // 每一行的唯一标识
          index,       // 索引号
          style        // 重点属性:一定要给每一个行数添加该样式
          isScrolling, // 当前列表是否在滚动中
          isVisible,   //这一行是否在列表中可见
          }) {
            if(flag) {
              return <div>
                  数据正在加载中
                  <!-- 也可以使用组件渲染一个骨架屏 -->
                    </div>
            }
            return (
              <div key={key} style={style}>
                {list[index]}
              </div>
            );
        }

结尾

  • 虽然这个组件需要不停的套娃,但同时也是一款非常优秀的组件,同时还有许多其他的功能,比如宫格组件GridTabel,都可以来实现可视区域的动态加载,优化性能。
  • tips
    • 在使用高阶组件进行包装的时候可能会出现报错,可能是因为,没有把包装的组件return,我们可以自己加上一个return