antd 의 select 드 롭 다운 상 자 는 데이터 양 이 너무 많아 서 카드 가 걸 리 는 해결 방식 입 니 다.

antd 를 사용 한 친구 들 은 기본적으로 select 드 롭 다운 상 자 를 사용 한 적 이 있다 고 믿 습 니 다.이 구성 요소 의 데이터 양 이 적 을 때 사용 하기 좋 습 니 다.그러나 데이터 양 이 많 을 때 예 를 들 어 몇 백 개,수천 개,심지어 수천 개 일 때 사용 하기 가 전혀 좋 지 않 습 니 다.카드 의 저 는 인생 을 의심 하고 사용자 체험 이 전혀 없습니다.
물론 이것 은 내 가 그것 의 동력 을 최적화 시 키 고 싶 은 것 이 아니 라 주로 회사 업무 인원 과 백 엔 드 의 동료 들 도 참 을 수 없 기 때문에 나 는 그들의 음위 에 굴복 할 수 밖 에 없다.
최적화 하려 면 왜 카드 가 걸 리 는 지 알 아야 합 니 다.초보적인 판단 은 데이터 양 이 너무 많아 서 렌 더 링 option 구성 요소 의 시간 이 너무 길 어서 카드 가 걸 리 지 않 으 려 면 렌 더 링 데이터 수량 만 제한 할 수 있 습 니 다.
제 생각 은 이 렇 습 니 다.항상 100 개의 데 이 터 를 렌 더 링 하여 멈 추 지 않도록 합 니 다.그리고 검색 이 필요 할 때 배경 에서 받 은 데 이 터 를 걸 러 내 고 100 개의 데이터 만 가 져 옵 니 다.그리고 select 상자 가 내 려 가지 않 을 때 초점 을 잃 었 을 때 데 이 터 를 그대로 복원 합 니 다.
다음은 나의 구체 적 인 실현 이다.
먼저 배경 에서 데 이 터 를 가 져 와 변수 fundList 에 저장 한 다음 에 그 중의 100 개의 데 이 터 를 취하 여 fundList 에 저장 합 니 다.드 롭 다운 상자 에 사용 할 데이터 렌 더 링
{fundList_.map(item => )}
이것 은 전체 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>
그리고 검색 기능 을 적어 주세요.

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"));
사실 두 가지 방법 은 각각 우열 이 있 습 니 다.첫 번 째 방법 은 렉 이 없 지만 보 여 주 는 데 이 터 량 은 어떤 사람 에 게 는 부족 할 수 있 습 니 다.두 번 째 방법 은 드 롭 다운 에 렉 이 없 지만 많은 데 이 터 를 굴 렸 을 때 구 르 면 약간 카드 가 있 고 특정한 증 거 를 선택 하 는 것 도 약간 카드 가 있 습 니 다.그래서 장면 봤 어 요.
질문
긴 말 안 할 게 요.그냥 코드 보 세 요~

<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 드 롭 다운 상 자 는 데이터 양 이 너무 많아 서 카드 가 걸 리 는 해결 방식 은 바로 작은 편집 이 여러분 에 게 공유 하 는 모든 내용 입 니 다.참고 하 실 수 있 고 많은 응원 부 탁 드 리 겠 습 니 다.

좋은 웹페이지 즐겨찾기