基於Ant Design Select組件react
📙 項目地址 :git
👉 GitHub地址: https://github.com/zlinggnilz/work-demo/blob/master/src/components/CustomSelect/index.jsgithub
👉 查看在線示例:https://codesandbox.io/s/funny-worker-lrhvt數組
📘 定製化組件 CustomSelect :antd
不傳入children,經過dataSource傳入數組遍歷出option,數組元素包含key 和 labelui
組件 CustomSelect 代碼:this
import React from "react"; import { Select } from "antd"; import PropTypes from "prop-types"; const { Option } = Select; export default class CustomSelect extends React.Component { static propTypes = { dataSource: PropTypes.arrayOf( PropTypes.shape({ key: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) .isRequired, label: PropTypes.string }) ), onChange: PropTypes.func }; static defaultProps = { dataSource: [] }; constructor(props) { super(props); this.state = { page: 1, showArr: props.dataSource }; this.pageSize = 20; this.list = []; } pageSt = 0; handleChange = v => { const { onChange, dataSource } = this.props; onChange && onChange(v); this.setState({ page: 1, showArr: dataSource }); }; handlePopupScroll = e => { const { page, showArr } = this.state; e.persist(); const { target } = e; const st = target.scrollTop; if (st === 0 && this.pageSt) { target.scrollTop = this.pageSt; } if ( st + target.offsetHeight + 2 >= target.scrollHeight && this.list.length < showArr.length ) { this.setState({ page: page + 1 }); this.pageSt = st; } else { this.pageSt = 0; } }; handleFocus = () => { this.prevScroll = 0; const { dataSource } = this.props; this.setState({ page: 1, showArr: dataSource }); }; handleSearch = v => { const { dataSource } = this.props; v = v || ""; const filterWord = v.trim().toLowerCase(); const showArr = dataSource.filter(item => item.label.toLowerCase().includes(filterWord) ); this.setState({ page: 1, showArr }); }; render() { const { dataSource, ...rest } = this.props; const { showArr, page } = this.state; if (showArr.length > this.pageSize) { this.list = showArr.slice(0, this.pageSize * page); // 當value是外部賦值的時候,判斷value是否在當前的list中,若是不在,單獨加進來 if (this.props.value != null) { let valueObj = this.list.find(item => item.key === this.props.value); if (!valueObj) { valueObj = dataSource.find(item => item.key === this.props.value); valueObj && this.list.unshift(valueObj); } } } else { this.list = showArr; } return ( <Select {...rest} onChange={this.handleChange} filterOption={false} onPopupScroll={this.handlePopupScroll} onFocus={this.handleFocus} onSearch={this.handleSearch} > {this.list.map(opt => ( <Option key={opt.key} value={opt.key}> {opt.label || opt.key} </Option> ))} </Select> ); } }
使用示例:spa
const SearchInput = () => { const arr = [{ label: "test text", key: "test" }]; for (let i = 0; i < 500; i++) { arr.push({ label: `label-${i}`, key: i, }); } return <CustomSelect showSearch dataSource={arr} placeholder="Custom select" style={{ width: 180 }} />; };
📚參考:rest