需求
利用Antd的Table組件可以實(shí)現(xiàn)表格的展示,表格數(shù)據(jù)是動(dòng)態(tài)增加的,并且表格數(shù)據(jù)的請(qǐng)求為異步請(qǐng)求。當(dāng)數(shù)據(jù)條數(shù)較大時(shí),需保證加載速度。
初始代碼結(jié)構(gòu):
首先,頁(yè)面結(jié)構(gòu)如下:
render() {
const {showProcess, data, length} = this.state
return (
<>
<Table
columns={tableHead}
dataSource={data}
></Table>
<Modal
visible={showProcess}
>
<Progress
type="circle"
percent={parseInt(`${(data.length / length) * 100}`)}
/>
</Modal>
</>
);
}
Table為Antd中的表格,表格數(shù)據(jù)為data,最終的總數(shù)據(jù)長(zhǎng)度為length,length為已知數(shù)據(jù)。Modal為顯示數(shù)據(jù)加載進(jìn)程的彈出框,加載進(jìn)程根據(jù)數(shù)據(jù)加載條數(shù)決定,其顯示狀態(tài)由showProcess控制。
動(dòng)態(tài)加載部分:
componentDidMount(){
const {data, length} = this.state
let i = 1
//異步動(dòng)態(tài)加入數(shù)據(jù)
let interval = setInterval(() => {
if(i<= length){
data.push({
key: String(i),
order: String(i),
name: '張三',
age: 13,
hobby: '乒乓',
home: '山東',
})
this.setState({data: data})
console.log(i)
i++
}else{
//數(shù)據(jù)加載全部完成,取消Modal框并清除interval
this.setState({showProcess: false})
clear()
}
}, 10);
let clear=()=>{
clearInterval(interval)
}
}
由于需要?jiǎng)討B(tài)載入,則需將數(shù)據(jù)的動(dòng)態(tài)填充放入componentDidMount中,它是在render函數(shù)之后執(zhí)行的。
代碼問(wèn)題:以上代碼可以實(shí)現(xiàn)數(shù)據(jù)動(dòng)態(tài)加載效果,但是如果數(shù)據(jù)條數(shù)較大時(shí),會(huì)出現(xiàn)加載緩慢問(wèn)題。加載緩慢原因是由于每次Push一條數(shù)據(jù)時(shí),都對(duì)表格數(shù)據(jù)進(jìn)行了更新,每一次更新都會(huì)觸發(fā)render函數(shù)的執(zhí)行,DOM操作較大,影響性能。
優(yōu)化后代碼
為了解決加載速度慢的問(wèn)題,可采取前20條數(shù)據(jù)載入后更新Table的data狀態(tài),以便于頁(yè)面視覺(jué)上保證數(shù)據(jù)一條條增加,而后面的數(shù)據(jù)可全部加載完再塞入Table中,避免頻繁的觸發(fā)render,影響性能。
以下為更改后的異步請(qǐng)求數(shù)據(jù)的函數(shù):
let interval = setInterval(() => {
if(i<= length){
data.push({
key: String(i),
order: String(i),
name: '張三',
age: 13,
hobby: '乒乓',
home: '山東',
})
//新增代碼,加入判斷條件
if(i<=20){
this.setState({data: data})
}
console.log(i)
i++
}else{
//數(shù)據(jù)加載全部完成,取消Modal框并清除interval
this.setState({showProcess: false})
//新增代碼,完成后統(tǒng)一setState data
this.setState({data: data})
clear()
}
}, 10);
以上代碼可以實(shí)現(xiàn)頁(yè)面加載速度的提高,但這樣Modal組件中的data也不會(huì)動(dòng)態(tài)更新了,如果動(dòng)態(tài)更新數(shù)據(jù)長(zhǎng)度,那render函數(shù)也會(huì)動(dòng)態(tài)執(zhí)行,因此將Modal組件分割為一個(gè)子組件,每次數(shù)據(jù)動(dòng)態(tài)載入后,都觸發(fā)該子組件中的方法,增加其數(shù)據(jù)長(zhǎng)度。
Modal子組件中加入以下方法:
//關(guān)閉Modal提示
close = () => {
this.setState({showProcess: false})
}
//組件中的數(shù)據(jù)長(zhǎng)度增加
addLength = () => {
const {curLen} = this.state
this.setState({curLen: curLen + 1})
}
總長(zhǎng)度length以屬性方法傳入子組件,curLen為加載了的數(shù)據(jù)長(zhǎng)度。
父組件:
let interval = setInterval(() => {
if(i<= length){
data.push({
key: String(i),
order: String(i),
name: '張三',
age: 13,
hobby: '乒乓',
home: '山東',
})
if(i<=20){
this.setState({data: data})
}
console.log(i)
//新增代碼
this.refs["modal"].addLength()
i++
}else{
//數(shù)據(jù)加載全部完成
this.setState({data: data})
//新增代碼
this.refs["modal"].close()
clear()
}
}, 10);
以上為用Typescript寫(xiě)的,以下附上ref的引用方式:
父組件中寫(xiě)入以下代碼即可使用ref。
refs:{
[key: string]: (any); // 類型聲明
modal:ModalProcess;
}
//引用
<ModalProcess ref = 'modal' length={length}/>
以上即解決了異步動(dòng)態(tài)加載過(guò)程中頻繁觸發(fā)render函數(shù)造成界面加載速度過(guò)慢的問(wèn)題。總結(jié)為:1. 不要頻繁觸發(fā)render,可以數(shù)據(jù)全部加載完后再觸發(fā)。 2. 如果必須一直需要?jiǎng)討B(tài)更新的,可以寫(xiě)入到子組件中,父組件調(diào)用子組件的方法以實(shí)現(xiàn)數(shù)據(jù)更新。