解決AutoComplete數據過多時的卡頓問題


  • 如下代碼,data數據超過2千條時,每次輸入字符過濾時非常卡
<AutoComplete
  dataSource={data}
  onChange={this.handleChange }
  allowClear={true}
  filterOption={
    (inputValue, option) => option.props.children.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1
  }
/>

其原因: 每次輸入變化,data就要從2000多條數據中過濾出目標元素,一過濾就導致AutoComplete下拉列表得變化,瀏覽器得重新繪制下拉列表的Dom,導致瀏覽器卡

解決辦法一

采用防抖函數,在間隔時間內,連續輸入字符串只在最后一個字符串發生時才觸發事件(onChange默認輸入內容已改變就觸發事件)

  • 防抖函數
let timer;
export const debounce = (func, wait ) => {
  // let timer = 0;
  return function(...args) {
    if (timer) clearTimeout(timer);

    timer = setTimeout(() => {
      func.apply(this, args);
    }, wait);
  };
};

  • 使用AutoComplete使用防抖函數
<AutoComplete
  dataSource={data}
  onChange={debounce(this.handleChange) }
/>


辦法一可以減少事件的觸發,但是仍然無法避免一個問題,就是首次點擊輸入框的時候特別卡,因為這個時候2000多條數據要一次被渲染
然而,沒有人會無聊到從2000多條數據滾動鼠標去查找自己的目標元素,都會通過輸入關鍵字符去過濾查找
所以首次沒必要加載這么多數據,可以默認截取原數據的前50條來顯示即可
后面在輸入框輸入關鍵詞后,將過濾好后的數據在賦給dataSource減少不必要的Dom渲染

解決辦法二,防抖和過濾二合一解決

  static getDerivedStateFromProps (props, state) {
    return{
      originDataLists: props.originDataLists,
      currentDataLists: state.currentDataLists.length>0 ?state.currentDataLists : props.currentDataLists.slice(1,100)
    }
  }
onChange = (value) => {
  const {originDataLists} = this.state
  const currentDataLists = originDataLists.filter(item = item.toUpperCase().includes(value.toUpperCase()))
  this.setState({currentDataLists});
};

render(){
  const {currentDataLists} = this.state
  return(
    <AutoComplete
      dataSource={currentDataLists}
      onChange={debounce(this.handleChange) }
    />
  )
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM