您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關antd的select下拉框因為數據量太大造成卡頓如何解決,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
先從后臺拿到數據,保存到變量fundList中(作為數據源,永遠不改動),然后取其中的前100條數據保存到fundList_中,用來下拉框的數據渲染
{fundList_.map(item => <Option key={item.fund} value={item.fund}>{item.name}</Option>)}
這是整個select組件:
<Select mode="multiple" maxTagCount={0} placeholder="請選擇" showSearch={true} onBlur={this.handleOnBlur} onSearch={this.handleOnSearch} allowClear={true} onChange={(value)=>{this.modalChangeSelect(value,'1')}} style={{width:'223px'}} value={record['1']||undefined} disabled={this.state.visibleType==='修改'?true:false} > {fundList_.map(item => <Option key={item.fund} value={item.fund}>{item.name}</Option>)} </Select>
然后寫search里面的功能
handleOnSearch = value => { // 函數節流,防止數據頻繁更新,每300毫秒才搜索一次 let that = this if (!this.timer) { this.timer = setTimeout(function(){ that.searchValue(value) that.timer = null },300) } } searchValue = (value) => { const datas = [] const {fundList} = this.state // 對fundList進行遍歷,將符合搜索條件的數據放入datas中 fundList.forEach(item => { if (item.name.indexOf(value) > -1) { datas.push(item) } }) // 然后只顯示符合搜索條件的所有數據中的前100條 this.setState({fundList_: datas.slice(0,100)}) }
當select失焦的時候,將數據恢復原樣(只顯示fundList中的前100條數據):
handleOnBlur = () => { this.setState({fundList_: this.state.fundList.slice(0,100)}) }
到此這個功能就大體實現了,已經不存在卡頓的問題了,但是這個方法并不是完美的,這不,業務就說了,你只顯示了前100條數據,但是我有時候不通過搜索功能查找某條數據,我要在所有的數據里面直接找到那條數據(業務也不嫌累。。。),我要顯示所有的數據。
這下就難辦了,因為卡頓就是渲染太多的數據造成的,所以還是不能一次性渲染所有的數據,然后怎么辦呢,我也不知道怎么辦吶。于是上網搜索了一下別人碰到相關問題的解決辦法,于是還真的找到了。
思路是這樣的:
同樣是先只展示前100條數據(這個沒辦法,想要不卡只能這樣),然后當滾動條滾到第100條數據也就是滾到底部的時候再增加100條,就這樣一直到展示所有的數據,下面是具體的實現步驟:
1、先造點假數據:
const data = []; for (let i = 0; i < 1000; i++) { data.push(`test${i}`); } // 一開始只展示前100條數據 const data_ = data.slice(0, 100);
2、渲染出來
<Select showSearch allowClear onPopupScroll={this.handleScroll} style={{ width: 200 }} placeholder="Select a person" optionFilterProp="children" onChange={this.onChange} onFocus={this.onFocus} onBlur={this.onBlur} onSearch={this.onSearch} filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 } > {optionData.map(item => ( <Option value={item}>{item}</Option> ))} </Select>
3、寫滾動條滾動的功能
在這里就要說一下select里面的一個參數了,就是 onPopupScroll,以前沒有注意到,看到別人提醒的時候才發現。有了它就可以實現滾動實時刷新數據了。
然后寫滾動的功能
handleScroll = e => { e.persist(); const { target } = e; // scrollHeight:代表包括當前不可見部分的元素的高度 // scrollTop:代表當有滾動條時滾動條向下滾動的距離,也就是元素頂部被遮住的高度 // clientHeight:包括padding但不包括border、水平滾動條、margin的元素的高度 const rmHeight = target.scrollHeight - target.scrollTop; const clHeight = target.clientHeight; // 當下拉框失焦的時候,也就是不下拉的時候 if (rmHeight === 0 && clHeight === 0) { this.setState({ scrollPage: 1 }); } else { // 當下拉框下拉并且滾動條到達底部的時候 // 可以看成是分頁,當滾動到底部的時候就翻到下一頁 if (rmHeight < clHeight + 5) { const { scrollPage } = this.state; this.setState({ scrollPage: scrollPage + 1 }); //調用處理數據的函數增加下一頁的數據 this.loadOption(scrollPage + 1); } } }; loadOption = pageIndex => { const { pageSize, keyWords } = this.state; // 通過每頁的數據條數和頁數得到總的需要展示的數據條數 const newPageSize = pageSize * (pageIndex || 1); let newOptionsData = [],len; // len 能展示的數據的最大條數 if (data.length > newPageSize) { // 如果總數據的條數大于需要展示的數據 len = newPageSize; } else { // 否則 len = data.length; } // 如果有搜索的話,就走這里 if (!!keyWords) { let data_ = data.filter(item => item.indexOf(keyWords) > -1) || []; data_.forEach((item, index) => { if (index < len) { newOptionsData.push(item); } }); } else { data.forEach((item, index) => { if (index < len) { newOptionsData.push(item); } }); } this.setState({ optionData: newOptionsData }); };
4、搜索功能:
和我剛開始的一樣
onSearch = val => { console.log("search:", val); if (!this.timer) { const that = this; this.timer = setTimeout(function() { that.searchValue(val); that.timer = null; }, 300); } this.setState({ keyWords: val }); }; searchValue = value => { let data_ = data.filter(item => item.indexOf(value) > -1); if (data_.length > 100 || value === "") { data_ = data_.slice(0, 100); } this.setState({ optionData: data_ }); };
5、 然后失焦的時候:
handleOnBlur = () => { this.setState({fundList_: this.state.fundList.slice(0,100)}) }
總的代碼:
import React from "react"; import ReactDOM from "react-dom"; import "antd/dist/antd.css"; import "./index.css"; import { Select } from "antd"; const { Option } = Select; const data = []; // let pageSize = 100,scrollPage = 1,keyWords = '',optionData = []; for (let i = 0; i < 1000; i++) { data.push(`test${i}`); } const data_ = data.slice(0, 100); class App extends React.Component { state = { pageSize: 100, scrollPage: 1, keyWords: "", optionData: data_ }; onChange = value => { console.log(`selected ${value}`); }; onBlur = () => { console.log("blur"); this.setState({ optionData: data_ }); }; onFocus = () => { console.log("focus"); }; onSearch = val => { console.log("search:", val); if (!this.timer) { const that = this; this.timer = setTimeout(function() { that.searchValue(val); that.timer = null; }, 300); } this.setState({ keyWords: val }); }; searchValue = value => { let data_ = data.filter(item => item.indexOf(value) > -1); if (data_.length > 100 || value === "") { data_ = data_.slice(0, 100); } this.setState({ optionData: data_ }); }; loadOption = pageIndex => { const { pageSize, keyWords } = this.state; const newPageSize = pageSize * (pageIndex || 1); let newOptionsData = [], len; if (data.length > newPageSize) { len = newPageSize; } else { len = data.length; } if (!!keyWords) { let data_ = data.filter(item => item.indexOf(keyWords) > -1) || []; data_.forEach((item, index) => { if (index < len) { newOptionsData.push(item); } }); } else { data.forEach((item, index) => { if (index < len) { newOptionsData.push(item); } }); } this.setState({ optionData: newOptionsData }); }; handleScroll = e => { e.persist(); const { target } = e; const rmHeight = target.scrollHeight - target.scrollTop; const clHeight = target.clientHeight; if (rmHeight === 0 && clHeight === 0) { this.setState({ scrollPage: 1 }); } else { if (rmHeight < clHeight + 5) { console.log(111, rmHeight, clHeight); const { scrollPage } = this.state; this.setState({ scrollPage: scrollPage + 1 }); // scrollPage = scrollPage + 1; this.loadOption(scrollPage + 1); } } // console.log(e.target) }; render() { const { optionData } = this.state; console.log(optionData.length); return ( <Select showSearch allowClear onPopupScroll={this.handleScroll} style={{ width: 200 }} placeholder="Select a person" optionFilterProp="children" onChange={this.onChange} onFocus={this.onFocus} onBlur={this.onBlur} onSearch={this.onSearch} filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 } > {optionData.map(item => ( <Option value={item}>{item}</Option> ))} </Select> ); } } ReactDOM.render(<App />, document.getElementById("container"));
其實兩個方法各有優劣,第一種的話沒有卡頓,但是展示的數據量對于有些人來說可能不太夠,而第二種方法呢雖然下拉沒有卡頓,但是當滾動了很多數據的時候滾動就會有點卡并且選擇某條數據也會有點卡。所以看場景了。
補充知識:VUE element select 選項內容顯示過長問題
我就廢話不多說了,大家還是直接看代碼吧~
<style> .el-select__tags-text { display: inline-block; max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .el-select .el-tag__close.el-icon-close { top: -7px; } </style>
關于antd的select下拉框因為數據量太大造成卡頓如何解決就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。