antd 3.X select scroll

2020-07-01  本文已影响0人  大乔是个美少女
// {value: 'aaa', label: 'bbb'}
// onNextPage(this.word, this.pages, FILTER_LENGTH);
// 搜索词、页数、页面数据量

import { Select } from "antd";
import debounce from "lodash/debounce";
import React, { Component } from "react";

const { Option } = Select;
const FILTER_LENGTH = 50;

class MyScrollSelect extends Component{

    filter_options = []; // 过滤规则选项
    pages = 1;
    word = '';

    static defaultProps = {
        placeholder: '请选择该字段',
        options: [],
        has_all_key: false, // 需不需要全部选项,全部选项默认ID为-1
        FILTER_LENGTH: FILTER_LENGTH,
    }

    state = {
        filter_options_for_show: [], // 过滤规则展示选项
        has_init_value: true, // 需要对初始化数据处理
    }

    // 异步初始化
    componentWillReceiveProps(nextProps) {
        if (nextProps.options.length > 0 && this.state.has_init_value) {
            setTimeout(() => {
                this.filterOption('')
            }, 0)
        }
    }

    // 过滤列表
    filterOption = async (input) => {
        let options = [], filters = [], origin_options = [];
        this.pages = 1;
        this.word = input;
        this.setState({ filter_options_for_show: []});
        // 支持远程
        if (this.props.onNextPage) {
            let data = await this.props.onNextPage(this.word, this.pages, this.props.FILTER_LENGTH);
            if (data.length == 0) {
                return
            }
            origin_options = data;
        } else {
            origin_options = this.props.options;
        }

        // 如果有默认值,就把默认值挪到第一个位置
        if (this.props.value && this.state.has_init_value) {
            let initIndex = -1;
            for (let index in origin_options) {
                if (origin_options[index].value == this.props.value) {
                    initIndex = index;
                    break;
                }
            }
            origin_options.unshift(origin_options.splice(initIndex, 1)[0])
        }
        this.setState({ has_init_value: false });

        filters = origin_options.filter(
            (item) => {return (item.label.toLowerCase()).indexOf(input.toLowerCase()) > -1}
        )
        if (this.props.has_all_key) {
            filters.unshift({value: -1, label: '全部'})
        }

        this.filter_options = filters;
        options = filters.slice(0, this.props.FILTER_LENGTH)
        this.setState({'filter_options_for_show': options })
    }


    // 循环获取
    Scroll = async (e) => {
        e.persist();
        const { target } = e;
        if (this.state.filter_options_for_show.length < this.props.FILTER_LENGTH * this.pages) {
            return
        }
        if (target.scrollTop + target.offsetHeight === target.scrollHeight) {
            // 支持远程
            if (this.props.onNextPage) {
                let data = await this.props.onNextPage(this.word, this.pages, this.props.FILTER_LENGTH);
                if (data.length == 0) {
                    return
                }
                this.filter_options.concat(data);
            }

            this.pages += 1;
            let content = this.filter_options.length - this.pages * this.props.FILTER_LENGTH;
            if (content < -this.props.FILTER_LENGTH) { return }
            let options = this.filter_options.slice(0, FILTER_LENGTH * this.pages);

            this.setState({'filter_options_for_show': options})
            setTimeout(() => {
                target.scrollTop=target.scrollHeight - 1500;
            })

        }
    }

    focus = () => {
        if (this.props.options.length > 0) {
            this.pages = 1;
            this.filterOption('')
        }
    }

    filter = debounce(this.filterOption, 100);

    render () {
        return (
            <Select
                {...this.props}
                showSearch
                onChange={this.props.onChange}
                onPopupScroll={this.Scroll}
                placeholder={this.props.placeholder}
                onFocus={this.focus}
                filterOption={false}
                onSearch={(input, option) =>{this.filter(input)}}
                optionLabelProp="label"
            >
                {
                    this.state.filter_options_for_show.map((option) => {
                        return (
                            <Option key={option.value} value={option.value} label={option.label}>
                            {
                                this.props.has_hot_tags && option.is_hot && <i className={'iconhuo iconfont red margin-0'}></i>
                            }
                            {option.label}
                            </Option>
                            
                        )
                    })
                }
            </Select>
        )
    }
}

export default MyScrollSelect;

上一篇 下一篇

猜你喜欢

热点阅读