在展示大型列表和表格數(shù)據(jù), 如: 城市列表鸽心、通訊錄辣恋、微博等被环,會導(dǎo)致頁面不流暢威蕉、卡頓等性能問題。
原因: 大量的DOM節(jié)點的重繪和重排祖凫,設(shè)備老舊菇肃;導(dǎo)致移動設(shè)備耗電耗電加快段多,設(shè)備發(fā)熱捏检。
優(yōu)化方案: 1.懶渲染 2. react-virtualized (可視區(qū)域渲染)
懶渲染: 每次只渲染一部分?jǐn)?shù)據(jù)荞驴,加載更多時再渲染一部分?jǐn)?shù)據(jù);
優(yōu)點: 每次渲染一部分?jǐn)?shù)據(jù)贯城,數(shù)據(jù)塊
缺點: 等數(shù)據(jù)量加載到非常多時熊楼,頁面依然存在大量DOM節(jié)點,占用內(nèi)存過多能犯、降低瀏覽器性能;
react-virtualized: 可視區(qū)域渲染
github: https://github.com/bvaughn/react-virtualized
install: npm install react-virtualized
列表組件文檔: https://github.com/bvaughn/react-virtualized/blob/master/docs/List.md
import React, { Component } from 'react'
import 'react-virtualized/styles.css' //導(dǎo)入樣式
import {List} from 'react-virtualized'; //導(dǎo)入list組件
// List data as an array of strings
const list = Array(100).fill('mmmm')
function rowRenderer({
key, // 唯一值
index, // 索引號
isScrolling, // 是否在滾動中
isVisible, // 當(dāng)前行在list中是否可見
style, // 每行的樣式對象
}){
return (
<div key={key} style={style}>
{index} --- {list[index]} {isScrolling+''}
</div>
);
}
export default class index extends Component {
render() {
return (
<div>
<List width={300} height={300} rowCount={list.length} rowHeight={20} rowRenderer={rowRenderer}/>,
</div>
)
}
}
接下來需要導(dǎo)入AutoSizer組件讓list組件占滿屏幕
AutoSizer組件是通過render-props模式暴露width和height屬性鲫骗,將暴露的width&height設(shè)置給list組件,設(shè)置頁面的根元素高度100%踩晶,讓list占滿頁面执泰。再減去導(dǎo)航欄的高度,讓頁面不要出現(xiàn)全局滾動條合瓢,避免頂部導(dǎo)航欄滾動坦胶。
AutoSizer組件文檔: https://github.com/bvaughn/react-virtualized/blob/master/docs/AutoSizer.md
import React, { Component } from 'react'
import 'react-virtualized/styles.css' //導(dǎo)入樣式
import {List, AutoSizer} from 'react-virtualized'; //導(dǎo)入list組件
import './index.css'
export default class index extends Component {
state = {
list: Array(100).fill('mmmm'),
}
rowRenderer = ({key, index, isScrolling, isVisible, style,})=>{
return this.state.list.map((item,index)=>{
return (
<div key={index} style={style}>
<div className="item-name">{item}</div>
</div>
)
})
}
render() {
return (
<div className="city-list">
<div className="nav-bar">title</div>
<AutoSizer>
{({height, width}) => (
<List
height={height}
rowCount={this.state.list.length}
rowHeight={ 50} //高度是item-name的css高度
rowRenderer={this.rowRenderer}
width={width}
/>
)}
</AutoSizer>
</div>
)
}
}
.city-list{
/* 減去nav-bar的高度 */
height: calc(100% - 45px)
}
#root,.App{
width: 100%;
height: 100%;
}
.nav-bar{
width: 100%;
height: 45px;
line-height: 45px;
background: orange;
color: #fff;
text-align: center;
}
.item-name{
width: 100%;
height: 50px;
line-height: 50px;
padding: 0 15px;
border-bottom: 1px solid #eee;
font-size: 16px;
color: #333;
background: #fff;
cursor: pointer;
}