UNPKG

ttk-app-core

Version:
248 lines (232 loc) 8.44 kB
import React from 'react' import Spin from '../spin/index' import {Select} from 'antd' const Option = Select.Option export default class LazySelect extends React.Component{ constructor(props) { super(props) this.state = { scrollTop: 0, rowHeight: props.rowHeight || 31.6, showRows: props.showRows || 100, scorllY: props.scorllY || 250, value: props.value } this.top = 0 this.isRender = false this.className = `lazy_select_${Math.floor(Math.random()*10000)}` } componentWillReceiveProps(nextProps) { if( nextProps.value !== this.state.value ) { const { children, value } = nextProps if( children && children instanceof Array ) { const single = children.find(item => { return item.props.value == value }) this.setState({ value: value, children: single ? single.props.children : value }) } } } componentDidUpdate = () => { const dom = document.querySelector(`.${this.className}`) if( dom ) { dom.querySelector('.ant-select-dropdown-menu').scrollTop = this.state.scrollTop setTimeout(() => { dom.querySelector('.ant-select-dropdown-menu').scrollTop = this.state.scrollTop }, 50) } setTimeout(() => { this.isRender = false }, 200) this.hiddenSpin() } hiddenSpin = () => { const dom2 = document.querySelector(`.${this.className}`) && document.querySelector(`.${this.className}`).querySelector('.ant-select-dropdown-menu') if( dom2 ) { const lastDom = dom2.querySelector('.lazy_select_last') if( lastDom ) { lastDom.querySelector('.lazy_select_last_spin').style.opacity = '0' } } } showSpin = () => { const dom = document.querySelector(`.${this.className}`).querySelector('.ant-select-dropdown-menu') // const top = dom.scrollTop // const firstDom = dom.querySelector('.lazy_select_first') const lastDom = dom.querySelector('.lazy_select_last') // if( firstDom ) { // const height = firstDom.offsetHeight // if( true ) { // console.log('显示 first') // firstDom.querySelector('.lazy_select_first_spin').style.display = 'block' // } // }else if( lastDom ) { // const containerHeight = document.querySelector(`.${this.className}`).offsetHeight // const sumheight = dom.offsetHeight, height = lastDom.offsetHeight if( true ) { console.log('显示') lastDom.querySelector('.lazy_select_last_spin').style.opacity = '1' } setTimeout(()=>{ this.hiddenSpin() }, 300) } } componentDidMount = () => { document.body.addEventListener('scroll', this.onPopupScroll, false) } onPopupScroll = (e) => { this.showSpin() if( this.isRender ) { return } const keyRandom = Math.floor(Math.random()*1000000) this.keyRandom = keyRandom setTimeout(()=>{ const dom = document.querySelector(`.${this.className}`).querySelector('.ant-select-dropdown-menu') const top = dom.scrollTop if( top == this.state.scrollTop ) { return } if( this.keyRandom == keyRandom) { this.setState({ scrollTop: top }) } setTimeout(()=>{ this.hiddenSpin() }, 0) }, 200) } getDataSource = (data = []) => { const { rowHeight, showRows, scorllY, scrollTop } = this.state, lens = data.length, sumHeight = lens * rowHeight, dataHeight = rowHeight * showRows, polyFillHeight = (dataHeight - scorllY)/2 let firstHeight = 0,lastHeight = 0 if( scrollTop <=polyFillHeight ) { lastHeight = sumHeight - dataHeight }else { firstHeight = scrollTop - polyFillHeight lastHeight = sumHeight - firstHeight - dataHeight } let dataStart = Math.floor(firstHeight/rowHeight) let dataEnd = dataStart + showRows const data2 = data.slice(dataStart, dataEnd) if( firstHeight > 0 ) { data2.unshift( <Option className="lazy_select_first" key='first' value="lazy_select_first" style={{ height: `${firstHeight}px`, position: 'static' }} > <span> </span> </Option> ) } if( data.length > 0 ) { data2.push( <Option key='last' className="lazy_select_last" value="lazy_select_last" style={{ height: `${lastHeight < 0 ? 0 : lastHeight}px`, position: 'static', background: '#fff' }} > <span> </span> <div key={data.length} className="lazy_select_last_spin" style={{ position: 'absolute', left: '0px', top: '0px', height: '100%', width: '100%', opacity: '0', pointerEvents: 'none', textAlign: 'center', zIndex: '111111111111' }} > <Spin style={{marginTop: '100px'}} delay={0}></Spin> </div> </Option> ) } this.showOption = data2 return data2 } handleChange = (value) => { if( value && typeof value == 'string' && value.includes('lazy_select') ) { return } const showOption = this.showOption const single = showOption.find(item => { return item.props && item.props.value == value }) this.setState({ value: value, children: single ? single.props.children : value, searchValue: '' }) this.props.onChange && this.props.onChange(value) } handleSearch = (value) => { const { showSearch, onSearch } = this.props if( showSearch ) { return onSearch(value) } this.setState({ searchValue: value }) } render() { this.isRender = true const props = this.props const data = props.children const { children, value, searchValue } = this.state const { dropdownClassName, filterOption } = props let optionArr if( searchValue && filterOption) { optionArr = data.filter((item) => { return filterOption(searchValue, item) }) }else{ optionArr = data } const option = this.getDataSource(optionArr) let flag = true if( value != null || value != undefined ) { flag = option.find(item => { return item.props.value == value }) } return ( <Select {...props} onChange={this.handleChange} dropdownClassName= {`${this.className}${dropdownClassName ? ` ${dropdownClassName}` : ''}`} onPopupScroll={this.onPopupScroll} showSearch={ props.showSearch ? props.showSearch : filterOption ? true : false } onSearch={ this.handleSearch } value={ flag ? value : children } dropdownStyle={{position: 'relative'}} > {option} </Select> ) } }