大数据渲染解决方案一 — react-virtualized

前端怎么处理大数据渲染

awak, DOM结构如果过大, 网页就会出现用户操作体验上的问题, 比如滚动, 点击等常用操作. 同时, 对react的虚拟DOM计算以及虚拟DOM反映到真实DOM的压力也会很大. 当用户点击切换按钮时, 就会出现秒级的卡顿.

解决问题核心:只加载可见区域的组件

react-virtualized是一个以高效渲染大型列表和表格数据的响应式组件

推荐:https://github.com/bvaughn/react-virtualized

react-virtualized的基础组件有:

  • Grid (推荐)

  • List

  • Table

  • Masonry

  • Collection

除此之外,还有些高阶组件。这里grid组件比较适合做网格的,做表格也是可以的,灵活度很高。list可以做排版类的长文列表。搭配 AutoSizer, InfiniteLoader, CellMeasurer, CellMeasurerCache做样式自适应,无限滚动。

比如下拉框中无限滚动加载:

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import VirtualList from 'virtual-list';
<Select
value={value}
autoFocus
open={open}
onBlur={() => setOpen(false)}
onMouseEnter={() => setOpen(true)}
style={{minWidth: 200}}
dropdownRender={() => (
<div onMouseDown={(e) => e.preventDefault()}>
<div style={{minHeight: 200}}>
<VirtualList {...val} />{' '}
</div>
<small>
总数:{total} 已加载:{data.length}
</small>
</div>
)}
/>

// virtual-list 组件
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import {List, AutoSizer, InfiniteLoader, CellMeasurer, CellMeasurerCache} from 'react-virtualized';

const RowCell = styled.div`
position: relative;
display: block;
overflow: hidden;
color: rgba(0, 0, 0, 0.65);
font-weight: 400;
white-space: nowrap;
text-overflow: ellipsis;
cursor: pointer;
`;

const VirtualList = (props) => {
const cache = new CellMeasurerCache({
defaultHeight: 40,
minHeight: 0,
fixedWidth: true
});

const {total, data, handleChange, handleMore, optionText} = props;
function RowRenderer(opj) {
const {index, key, parent, style} = opj;
return (
<CellMeasurer cache={cache} columnIndex={0} key={key} parent={parent} rowIndex={index}>
<RowCell
style={style}
onClick={() => {
handleChange({index: index, item: data[index]});
}}
>
{optionText(data[index], index)}
</RowCell>
</CellMeasurer>
);
}

function handleHeight(height) {
return Math.min(data.length * cache.defaultHeight + 40, height);
}

return (
<AutoSizer style={{minHeight: 'max-content'}}>
{({width, height}) => {
return (
<InfiniteLoader
isRowLoaded={({index}) => {
return index < data.length;
}}
loadMoreRows={() => handleMore()}
rowCount={total}
threshold={2}
>
{({onRowsRendered, registerChild}) => {
return (
<List
height={handleHeight(height)}
onRowsRendered={onRowsRendered}
ref={registerChild}
rowCount={data.length}
rowHeight={cache.rowHeight}
deferredMeasurementCache={cache}
rowRenderer={RowRenderer}
width={width}
/>
);
}}
</InfiniteLoader>
);
}}
</AutoSizer>
);
};

VirtualList.propTypes = {
handleMore: PropTypes.func,
handleChange: PropTypes.func,
optionText: PropTypes.func,
data: PropTypes.array,
total: PropTypes.number
};

VirtualList.defaultProps = {
handleMore: () => {},
handleChange: () => {},
optionText: () => {},
data: [],
total: 0
};

export default VirtualList;

demo: https://bvaughn.github.io/react-virtualized/#/components/Table

另外:可参考https://github.com/bvaughn/react-window
同一个作者,体积更小,更快。demo: https://react-window.now.sh/#/examples/list/fixed-size

嵌入式持久性数据库 —— Nedb tabby:高颜值的终端工具

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×