# Select 下拉框

- 来源：[E10 UI 组件库](https://www.e-cology.com.cn/ui/select/freepass)
- 平台：PC
- 维护者：揭志胜
- 设计稿：http://pd.e-cology.com.cn/pd/E10/interface/e10xiaoguotu/PC/E10zjys/#s9
- Issue：http://gitlab.ecology10.cn/FRONTEND/weapp-ui/-/issues?state=all&search=[Select]

## 代码演示

### 基础用法

直接引入组件进行使用

```jsx
import React, { Component } from 'react';
import { constants, Select, SelectOptionData, SelectValueType, SingleType } from '@weapp/ui';

const prefixCls = `${constants.uiPcClsPrefix}-demo-input`;

type SelectDemoState = {
  value: string;
}

const options = [
  { id: '', content: '选项一', other: true, color: '#5D9CEC' },
  { id: '2', content: '选项二', custom: 3, color: '#FF4D4F' },
  { id: '3', content: '超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本', color: '#52C41A' },
  { id: '4', content: '禁用项', disabled: true }
];

class SelectDemo extends Component<any, SelectDemoState> {
  constructor(props: any) {
    super(props);
    this.state = {
      value: '',
    };
  }

  handleChange = (v: SelectValueType, option: any, event: any) => {
    console.log('handleChange')
    console.log('v', v)
    console.log('option', option)
    console.log('event', event)
    this.setState({ value: v as string })
  };

  handleSelect = (value: SingleType<SelectValueType>, option: SelectOptionData) => {
    console.log('selected:', value, option);
  }

  handleDeselect = (value: SingleType<SelectValueType>, option: SelectOptionData) => {
    console.log('deselected:', value, option);
  }
  onSelectClick = () => console.info('onSelectClick')

  render() {
    const { value } = this.state;
    return (
      <div className={prefixCls}>
        <h4>编辑</h4>
        <Select
          data={options}
          value={value}
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
          onChange={this.handleChange}
          onSelectClick={this.onSelectClick}
        />
        <h4>只读</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          value={'2'}
          readOnly
        />
        <h4>只读(文本过程情况)</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          value={'3'}
          readOnly
        />
        <h4>只读(无数据，展示 placeholder)</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          readOnly
          readOnlyShowPlaceholder
          placeholder='请选择'
        />
        <h4>禁用</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          value={'3'}
          disabled
        />
        <h4>最小宽度调整</h4>
        <Select
          data={options}
        />
        <h4>默认展开</h4>
        <Select
          defaultOpen
          style={{width: 250}}
          data={options}
          value={value}
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
          onChange={this.handleChange}
          onSelectClick={this.onSelectClick}
        />
      </div>
    );
  }
}

export default SelectDemo;
```

### 下拉框的多选样式

可以选择多个选项

```jsx
import React, { Component } from 'react';
import { constants, Select, SelectOptionData, SelectValueType } from '@weapp/ui';

type ValueType = string[] | SelectOptionData[];

const prefixCls = `${constants.uiPcClsPrefix}-demo-input`;

type SelectDemoState = {
  valueArr: string[];
}

const options = [
  { id: '1', content: '选项一', other: true, color: '#5D9CEC' },
  { id: '2', content: '选项二', custom: 3, color: '#FF4D4F' },
  { id: '3', content: '选项三内容比较多多选内容测试多选内容测试', color: '#52C41A' },
  { id: '4', content: '禁用项', disabled: true }
];

class SelectDemo extends Component<any, SelectDemoState> {
  constructor(props: any) {
    super(props);
    const largeOptions = [];
    for (let i = 0; i < 100; i++) {
      largeOptions.push({
        id: `${i}`,
        content: `选项${i + 1}`,
        red: i % 4 === 0
      });
    }
    this.state = {
      valueArr: ['1']
    };
  }

  handleArrChange = (v: SelectValueType) => this.setState({ valueArr: v as string[] });

  handleSelect = (value: ValueType[number], option: SelectOptionData) => {
    console.log('selected:', value, option);
  }

  handleDeselect = (value: ValueType[number], option: SelectOptionData) => {
    console.log('deselected:', value, option);
  }

  customOptionRender = (option: SelectOptionData) => {
    console.log('option', option)
    const { content, red } = option;
    if (red) {
      return (
        <span style={{ color: 'red' }}>{content}*</span>
      )
    }
    return (
      <span>{content}</span>
    );
  }

  render() {
    const { valueArr } = this.state;
    return (
      <div className={prefixCls}>
        <h4>编辑</h4>
        <Select
         
          style={{ width: 200 }}
          data={options}
          multiple
          value={valueArr}
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
          onChange={this.handleArrChange}
        />
        <h4>多选长文本</h4>
        <Select
         
          data={options}
          multiple
        />
        <h4>只读</h4>
        <Select
          style={{ width: 200 }}
          multiple
          readOnly
          value={valueArr}
          data={options}
        />
        <h4>只读（无数据，展示 placeholder）</h4>
        <Select
          style={{ width: 200 }}
          multiple
          readOnly
          placeholder='请选择'
          readOnlyShowPlaceholder
        />
        <h4>禁用</h4>
        <Select
          style={{ width: 200 }}
          multiple
          disabled
          value={valueArr}
          data={options}
        />
        <h4>编辑-竖向排列</h4>
        <Select
         
          style={{ width: 200 }}
          data={options}
          multiple
          vertical
          value={valueArr}
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
          onChange={this.handleArrChange}
        />
        <h4>多选长文本-竖向排列</h4>
        <Select
         
          data={options}
          multiple
          vertical
        />
        <h4>只读-竖向排列</h4>
        <Select
          style={{ width: 200 }}
          multiple
          readOnly
          vertical
          value={valueArr}
          data={options}
        />
        <h4>只读-竖向排列</h4>
        <Select
          style={{ width: 200 }}
          multiple
          vertical
          readOnly
          value={valueArr}
          placeholder='请选择'
          readOnlyShowPlaceholder
        />
        <h4>禁用-竖向排列</h4>
        <Select
          style={{ width: 200 }}
          multiple
          disabled
          vertical
          value={valueArr}
          data={options}
        />
      </div>
    );
  }
}

export default SelectDemo;
```

### 标签样式

直接引入组件进行使用

```jsx
import React, { Component, ReactElement } from 'react';
import { constants, Select, SelectOptionData, SelectValueType } from '@weapp/ui';
// import './tag.less'

type ValueType = string[] | SelectOptionData[];

const prefixCls = `${constants.uiPcClsPrefix}-demo-input`;

type SelectDemoState = {
  value: string;
  valueArr: string[];
}

const options = [
  { id: '1', content: '选项一', other: true, color: '#5D9CEC' },
  { id: '2', content: '选项二', custom: 3, color: '#FF4D4F' },
  { id: '3', content: '选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试', color: '#52C41A' },
  { id: '4', content: '禁用项', disabled: true },
  { id: '5', content: '选项五' },
  { id: '6', content: '选项一', other: true, color: '#5D9CEC' },
  { id: '7', content: '选项二', custom: 3, color: '#FF4D4F' },
  { id: '8', content: '选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试', color: '#52C41A' },
  { id: '9', content: '禁用项', disabled: true },
  { id: '10', content: '选项五' },
  { id: '11', content: '选项一', other: true, color: '#5D9CEC' },
  { id: '12', content: '选项二', custom: 3, color: '#FF4D4F' },
  { id: '13', content: '选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试', color: '#52C41A' },
  { id: '14', content: '禁用项', disabled: true },
  { id: '15', content: '选项五' }
];

const optionsMore = [
  { id: '1', content: '选项一', other: true, color: '#5D9CEC' },
  { id: '2', content: '选项二', custom: 3, color: '#FF4D4F', extraContent:"额外的文本内容", prefixContent: '前缀' },
  { id: '555', content: '无颜色选项', selectType: 'normal' },
  { id: '666', content: '白色选项',  color: 'white',extraContent:"额外的文本内容", prefixContent: '前缀' },
  { id: '777', content: '透明选项',  color: 'transparent' },
  { id: '3', content: '选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试选项一内容过长测试', color: '#52C41A' },
  { id: '4', content: '禁用项', disabled: true }
];

const optionsNoColor = [
  { id: '1', content: '选项一', other: true, selectType: 'normal'  },
  { id: '2', content: '选项二', custom: 3,  extraContent:"额外的文本内容", selectType: 'normal'  },
];

class SelectDemo extends Component<any, SelectDemoState> {
  constructor(props: any) {
    super(props);
    this.state = {
      value: '1',
      valueArr: ['1'],
    };
  }

  handleChange = (v: SelectValueType) => this.setState({ value: v as string });

  handleArrChange = (v: SelectValueType) => this.setState({ valueArr: v as string[] });

  handleSelect = (value: ValueType[number], option: SelectOptionData) => {
    console.log('selected:', value, option);
  }

  handleDeselect = (value: ValueType[number], option: SelectOptionData) => {
    console.log('deselected:', value, option);
  }

  customInputContentRender = (ele:  React.ReactNode) =>{
    return <div>框内内容复写{ele}</div>
  }

  customPrefixRender = (value: any, type?: string) => {
    if (type === 'selectedValues') {
      return <div key={value.id}>已选icon</div>
    } else if (type === 'options') {
      return <div key={value.id}>选项icon</div>
    } else {
      return <div key={value.id}>其他</div>
    }
  }

  render() {
    const { value, valueArr } = this.state;
    return (
      <div className={prefixCls}>
        <h4>单选</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          value={value}
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
          onChange={this.handleChange}
          optionType="tag"
        />
        <h4>单选(表单只读特殊样式)</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          value={'3'}
          optionType="tag"
          readOnly
          readOnlyLineHeightStandard
        />
        <h4>多选</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          multiple
          value={valueArr}
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
          onChange={this.handleArrChange}
          optionType='tag'
        />

        <h4>多选(支持全选)</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          multiple
          value={valueArr}
          allowSelectAll
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
          onChange={this.handleArrChange}
          optionType='tag'
        />
        <h4>单选(只读)</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          value={'3'}
          optionType="tag"
          readOnly
        />
        <h4>单选(只读，无数据，展示 placeholder)</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          optionType="tag"
          readOnly
          placeholder='请选择'
          readOnlyShowPlaceholder
        />

        <h4>单选(只读-跟标准模式下高度保持一致)</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          value={'3'}
          optionType="tag"
          readOnly
          showDefaultWrap
        />

        <h4>多选(只读)</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          multiple
          // value={'3'}
          value={['3','2']}
          optionType='tag'
          readOnly
        />
        <h4>多选(只读，无数据，展示 placeholder)</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          multiple
          optionType='tag'
          readOnly
          readOnlyShowPlaceholder
          placeholder='请选择'
        />

        <h4>多选(只读-表单行高对齐)</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          multiple
          value={['3','2']}
          optionType='tag'
          readOnly
          readOnlyLineHeightStandard
        />

        <h4>单选(额外内容显示)</h4>
        <div style={{marginBottom:'10px'}}>
          配置的options 除了content,支持配置extraContent, prefixContent 设置额外的文本内容
        </div>
        <Select
          style={{ width: 200 }}
          data={optionsMore}
          showSearch
          optionType='tag'
          customPrefixRender={this.customPrefixRender}
        />

        <h4>单选(额外内容显示,只读)</h4>
        <div style={{marginBottom:'10px'}}>
          配置的options 除了content,支持配置extraContent, prefixContent 设置额外的文本内容
        </div>
        <Select
          data={optionsMore}
          value={'2'}
          showSearch
          readOnly
          optionType='tag'
          customPrefixRender={this.customPrefixRender}
        />

        <h4>单选(不设置tag颜色)</h4>
        <div style={{marginBottom:'10px'}}>
          设置选项 selectType: 'normal'
        </div>
        <Select
          style={{ width: 200 }}
          data={optionsNoColor}
          showSearch
          optionType='tag'
        />

        <h4>单选(只读文本不省略全展示,定宽)</h4>
        <div style={{marginBottom:'10px'}}>
            selectedWrap 允许折行
        </div>
        <Select
          style={{ width: 200 }}
          data={optionsMore}
          showSearch
          readOnly
          selectedWrap
          value={'3'}
          optionType='tag'
        />

        <h4>单选(只读文本不省略全展示,定宽)</h4>
        <div style={{marginBottom:'10px'}}>
            selectedWrap, 允许折行。readOnlyLineHeightStandard 固定高度比例
        </div>
        <Select
          style={{ width: 200 }}
          data={optionsMore}
          showSearch
          readOnly
          selectedWrap
          value={'3'}
          optionType='tag'
          readOnlyLineHeightStandard
        />

        <h4>单选(只读文本不省略全展示,非定宽)</h4>
        <div style={{marginBottom:'10px'}}>
            selectedWrap 允许折行
        </div>
        <Select
          data={optionsMore}
          showSearch
          readOnly
          selectedWrap
          value={'3'}
          optionType='tag'
        />
      
        <h4>多选(额外内容显示)</h4>
        <div style={{marginBottom:'10px'}}>
          配置的options 除了content,支持配置extraContent, prefixContent 设置额外的文本内容
        </div>
        <Select
          style={{ width: 200 }}
          data={optionsMore}
          showSearch
          multiple
          optionType='tag'
          customPrefixRender={this.customPrefixRender}
        />

        <h4>多选(只读文本不省略全展示)</h4>
        <div style={{marginBottom:'10px'}}>
            selectedWrap 允许折行
        </div>
        <Select
          style={{ width: 200 }}
          data={optionsMore}
          showSearch
          multiple
          readOnly
          selectedWrap
          value={['3','2']}
          optionType='tag'
        />

        <h4>tag模式下支持复写已选区域()</h4>
        <div style={{marginBottom:'10px'}}>
          customInputContentRender
        </div>
        <Select
          style={{ width: 200 }}
          data={optionsMore}
          multiple
          optionType='tag'
          customInputContentRender={this.customInputContentRender}
        />

      </div>
    );
  }
}

export default SelectDemo;
```

### 分组

备选项进行分组展示

```jsx
import React, { Component } from 'react';
import { constants, Select, SelectOptionData, SelectValueType, SingleType } from '@weapp/ui';

const prefixCls = `${constants.uiPcClsPrefix}-demo-input`;

type SelectDemoState = {
  valueObj: SelectOptionData;
};

const groupOptions = [
  { id: '11', content: '选项一', type: '1' },
  { id: '12', content: '禁用项', type: '1', disabled: true },
  { id: '13', content: '选项三', type: '1' },
  { id: '21', content: '选项四', type: '2' },
  { id: '31', content: '选项五', type: '3' },
];

const groupTitle = [
  { id: '1', content: '分组1' },
  { id: '2', content: '分组2' },
  { id: '3', content: '分组3' }
];

class SelectDemo extends Component<any, SelectDemoState> {
  constructor(props: any) {
    super(props);
    const largeOptions = [];
    for(let i = 0; i < 100; i ++) {
      largeOptions.push({
        id: `${i}`,
        content: `选项${i + 1}`,
        red: i % 4 === 0
      });
    }
    this.state = {
        valueObj: groupOptions[0],
    };
  }

  handleObjChange = (v: SelectValueType) => this.setState({ valueObj: v as SelectOptionData });

  handleSelect = (value: SingleType<SelectValueType>, option: SelectOptionData) => {
    console.log('selected:', value, option);
  }

  handleDeselect = (value: SingleType<SelectValueType>, option: SelectOptionData) => {
    console.log('deselected:', value, option);
  }

  render() {
    const { valueObj} = this.state;
    return (
      <div className={prefixCls}>
        <Select
          style={{ width: 200 }}
          data={groupOptions}
          showDataGroupByType
          dataGroupTitle={groupTitle}
          value={valueObj}
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
          onChange={this.handleObjChange}
        />
      </div>
    );
  }
}

export default SelectDemo;
```

### 可搜索的下拉框

可以利用搜索功能快速查找选项

```jsx
import React, { Component } from 'react';
import { constants, Select, SelectOptionData, SelectValueType, SingleType } from '@weapp/ui';
import { info } from 'console';

const prefixCls = `${constants.uiPcClsPrefix}-demo-input`;

const options = [
  { id: '1', content: 'Jack', other: true },
  { id: '11', content: 'Jack2', other: true },
  { id: '2', content: 'Lucy', custom: 3 },
  { id: '3', content: 'Tom' },
  { id: '8', content: 'disabled', disabled: true }
];

const style = { width: 200 };

const style2 = { width: 150 };

class SelectDemo extends Component {
  constructor(props: any) {
    super(props);
    const largeOptions = [];
    for(let i = 0; i < 100; i ++) {
      largeOptions.push({
        id: `${i}`,
        content: `选项${i + 1}`,
        red: i % 4 === 0
      });
    }
    this.state = {
      visible: false,
    };
  }

  handleSelect = (value: SingleType<SelectValueType>, option: SelectOptionData) => {
    console.log('selected:', value, option);
  }

  handleKeyDown = (e: any) => {
    console.info('keyDown',e)
  }

  handleDeselect = (value: SingleType<SelectValueType>, option: SelectOptionData) => {
    console.log('deselected:', value, option);
  }

  filterOption = (inputValue: string, option: SelectOptionData): boolean => {
    // 比较时忽略大小写
    const patt = new RegExp(inputValue, 'ig');
    return patt.test(option.content || '');
  }

  handleChange = (value: any) => {
    console.log('value',value);
    
  }

  render() {
    return (
      <div className={prefixCls}>
        <h4>默认搜索</h4>
        <Select
          style={style}
          data={options}
          showSearch
          onChange={this.handleChange}
          onKeyDown={this.handleKeyDown}
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
        />

        <h4>默认搜索</h4>
        <Select
          style={style2}
          data={options}
          showSearch
          onChange={this.handleChange}
          onKeyDown={this.handleKeyDown}
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
        />
        <h4>自定义搜索</h4>
        <Select
          style={style}
          data={options}
          showSearch
          filterOption={this.filterOption}
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
        />
        <h4>多选</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          multiple
          allowSelectAll
          showSearch
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
        />
      </div>
    );
  }
}

export default SelectDemo;
```

### 自定义渲染

自定义下拉框选项和已选数据的渲染

```jsx
import React, {Component, ReactNode} from 'react';
import {constants, Icon, Input, Select, SelectOptionData, SelectOptionsType, SelectValueType, SelectCustomTagProps} from '@weapp/ui';

const { InputWrap } = Input;

type ValueType = string[] | SelectOptionData[];

const prefixCls = `${constants.uiPcClsPrefix}-demo-select`;

type SelectDemoState = {
  valueArr: string[];
}

const options = [
  { id: '1', content: '选项一', other: true, color: '#5D9CEC' },
  { id: '2', content: '选项二', custom: 3, color: '#FF4D4F', red: true },
  { id: '3', content: '选项三', color: '#52C41A' },
  { id: '4', content: '禁用项', disabled: true }
];

class SelectDemo extends Component<any, SelectDemoState> {
  constructor(props: any) {
    super(props);
    const largeOptions = [];
    for(let i = 0; i < 100; i ++) {
      largeOptions.push({
        id: `${i}`,
        content: `选项${i + 1}`,
        red: i % 4 === 0
      });
    }
    this.state = {
      valueArr: ['1']
    };
  }

  handleArrChange = (v: SelectValueType) => this.setState({ valueArr: v as string[] });

  handleSelect = (value: ValueType[number], option: SelectOptionData) => {
    console.log('selected:', value, option);
  }

  handleDeselect = (value: ValueType[number], option: SelectOptionData) => {
    console.log('deselected:', value, option);
  }

  tagRender = (props: SelectCustomTagProps) => {
    const { id, content, closable, onClose } = props;
    return (
      <span className={`${prefixCls}-custom-tag`} key={id}>
        {content}
        {closable && <Icon name="Icon-error02" onClick={onClose} /> }
      </span>
    );
  }

  customOptionRender = (option: SelectOptionData) => {
    console.log('option', option)
    const { content, red } = option;
    if (red) {
      return <span style={{ color: 'red' }}>{content}*</span>;
    }
    return (
      <span>{content}</span>
    );
  }

  customInputRender = (selectComponent:any, selectedData: SelectOptionsType) => {
    let inputEle: ReactNode;
    if (selectedData.length) {
      inputEle = selectComponent.renderSelectedValues();
    } else {
      inputEle = selectComponent.renderPlaceholder();
    }
    return(
      <div className={`${prefixCls}-custom-input-wrap`}>
        <InputWrap
         
          style={{ width: 200 }}
          prefix="选择:"
          suffix={<Icon size={'s'} name="Icon-search"/>}
          element={<>{inputEle}</>}
        />
      </div>
    )
  }

  render() {
    const {  valueArr} = this.state;
    return (
      <div className={prefixCls}>
        <h4>自定义下拉选项</h4>
        <Select
         
          style={{ width: 200 }}
          multiple
          data={options}
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
          customOptionRender={this.customOptionRender}
        />
        <h4>自定义已选数据</h4>
        <Select
          style={{ width: 200 }}
          multiple
          data={options}
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
          tagRender={this.tagRender}
        />
        <h4>自定义输入框展示</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          allowCancel
          // multiple
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
          customInputRender={this.customInputRender}
        />
      </div>
    );
  }
}

export default SelectDemo;
```

### 其他功能

全选、取消选中、批量数据

```jsx
import React, { Component } from 'react';
import { constants, Select, SelectOptionData, SelectValueType, SingleType } from '@weapp/ui';

const prefixCls = `${constants.uiPcClsPrefix}-demo-input`;

type SelectDemoState = {
  visible: boolean;
  defaultValue: string[],
  largeOptions: SelectOptionData[];
}

const options = [
  { id: '1', content: '选项一', other: true, color: '#5D9CEC' },
  { id: '2', content: '选项二', custom: 3, color: '#FF4D4F', separator: true },
  { id: '3', content: '超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本', color: '#52C41A' },
  { id: '4', content: '禁用项', disabled: true }
];

class SelectDemo extends Component<any, SelectDemoState> {
  constructor(props: any) {
    super(props);
    const largeOptions = [];
    for(let i = 0; i < 100; i ++) {
      largeOptions.push({
        id: `${i}`,
        content: `选项${i + 1}`,
        red: i % 4 === 0
      });
    }
    this.state = {
      defaultValue: ['1', '3', '4'],
      visible: false,
      largeOptions
    };
  }

  handleSelect = (value: SingleType<SelectValueType>, option: SelectOptionData) => {
    console.log('selected:', value, option);
  }

  handleDeselect = (value: SingleType<SelectValueType>, option: SelectOptionData) => {
    console.log('deselected:', value, option);
  }

  render() {
    const { largeOptions, defaultValue } = this.state;
    return (
      <div className={prefixCls}>
        <h4>可取消选中 - 单选(此api 已无效取消对应反选效果)</h4>
        <Select
         
          style={{ width: 200 }}
          data={options}
          allowCancel
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
        />
        <h4>给选项添加分割线</h4>
        <p>给需要添加分隔线的选项加上 <b>separator</b> 字段即可</p>
        <Select
         
          style={{ width: 200 }}
          data={options}
          allowCancel
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
        />
        <h4>可全选 - 多选</h4>
        <Select
         
          style={{ width: 200 }}
          data={options}
          multiple
          allowSelectAll
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
        />
        <h4>大批量数据</h4>
        <Select
          style={{ width: 200 }}
          data={largeOptions}
          multiple
          showSearch
          allowSelectAll
          defaultValue={defaultValue}
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
        />

        <h4>可全选 - 多选(无数据情况下)</h4>
        <Select
         
          style={{ width: 200 }}
          multiple
          allowSelectAll
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
        />
      </div>
    );
  }
}

export default SelectDemo;
```

### 超出省略与折行展示

```jsx
import React, { Component } from 'react';
import { constants, Select, SelectOptionData, SelectValueType, SingleType } from '@weapp/ui';

const prefixCls = `${constants.uiPcClsPrefix}-demo-input`;

type SelectDemoState = {
  value: string;
}

const options = [
  { id: '1', content: '选项一', other: true, color: '#5D9CEC' },
  { id: '2', content: '选项二', custom: 3, color: '#FF4D4F' },
  { id: '3', content: '超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本', color: '#52C41A' },
  { id: '4', content: '禁用项', disabled: true }
];

class SelectDemo extends Component<any, SelectDemoState> {
  constructor(props: any) {
    super(props);
    this.state = {
      value: '3',
    };
  }

  handleChange = (v: SelectValueType, option: any, event: any) => {
    console.log('handleChange')
    console.log('v', v)
    console.log('option', option)
    console.log('event', event)
    this.setState({ value: v as string })
  };

  handleSelect = (value: SingleType<SelectValueType>, option: SelectOptionData) => {
    console.log('selected:', value, option);
  }

  handleDeselect = (value: SingleType<SelectValueType>, option: SelectOptionData) => {
    console.log('deselected:', value, option);
  }

  render() {
    const { value } = this.state;
    return (
      <div className={prefixCls}>
        <h4>select下拉框默认最小高度为30px</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          value={value}
          onSelect={this.handleSelect}
          onDeselect={this.handleDeselect}
          onChange={this.handleChange}
          readOnly
        />
        {/* <h4>高度自适应：input框默认含有高度自适应</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          defaultValue={'3'}
          readOnly
        /> */}
        <h4>折行展示：注意，单行文本只有只读模式下能够折行</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          defaultValue={'3'}
          selectedWrap
          readOnly
        />
        <h4>超出省略</h4>
        <Select
          style={{ width: 200 }}
          data={options}
          defaultValue={'3'}
          selectedWrap={false}
          readOnly
        />
      </div>
    );
  }
}

export default SelectDemo;
```

### 文本溢出下聚焦放大

需要放大有过渡效果需要手动设置对应宽度。默认效果聚焦放大后会撑开布局,若需要放大后不出现布局问题，需要手动设置focusAutoExpandProps属性,放大效果将默认使用绝对定位布局不影响后面布局。开启此属性时需要默认父级设置相对定位且不依赖子元素高度，避免出现布局问题。

```jsx
import React, { Component } from 'react';
import { constants, Select, SelectOptionData, SelectValueType, SingleType, Button } from '@weapp/ui';
const prefixCls = `ui-demo-select`;

type SelectDemoState = {
  value: string;
};

const options = [
  { id: '1', content: '选项一', other: true, color: '#5D9CEC' },
  { id: '2', content: '选项二', custom: 3, color: '#FF4D4F' },
  {
    id: '3',
    content: '超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本超长文本',
    color: '#52C41A',
  },
  { id: '4', content: '禁用项', disabled: true },
];

class SelectDemo extends Component<any, SelectDemoState> {
  constructor(props: any) {
    super(props);
    this.state = {
      value: '1',
    };
  }

  constainerRef: any = React.createRef();

  handleChange = (v: SelectValueType, option: any, event: any) => {
    this.setState({ value: v as string });
  };

  handleSelect = (value: SingleType<SelectValueType>, option: SelectOptionData) => {
    console.log('selected:', value, option);
  };

  handleDeselect = (value: SingleType<SelectValueType>, option: SelectOptionData) => {
    console.log('deselected:', value, option);
  };
  onSelectClick = () => console.info('onSelectClick');

  getWrapperContainer = () => {
    return this.constainerRef && this.constainerRef.current;
  };

  render() {
    return (
      <div className={prefixCls}>
        <h4>默认使用(不设置宽度的情况下,无过渡效果)</h4>
        <Select data={options} focusAutoExpand />
        <h4>过渡效果(添加focusAutoExpand)</h4>
        <div style={{ height: '40px' }}>
          <Select
           
            style={{ width: 200 }}
            data={options}
            focusAutoExpand
          />
        </div>
        <h4>指定外层容器限制最大宽度(getWrapperContainer)</h4>
        <div className={`${prefixCls}-focus`} ref={this.constainerRef}>
          <Select
           
            style={{ width: 200 }}
            data={options}
            focusAutoExpand
            focusAutoExpandProps={{
              autoExpandContainer: this.getWrapperContainer,
            }}
          />
          <Button style={{ marginLeft: 10 }}>
            左侧内容挡住
          </Button>
        </div>
        <h4>使用绝对定位不撑开布局(autoExpandUseAbsolute),手动设置父级相对定位</h4>
        <div style={{ height: '40px', marginLeft: 20, position: 'relative' }}>
          <Select
           
            style={{ width: 200 }}
            data={options}
            focusAutoExpand
            focusAutoExpandProps={{
              autoExpandUseAbsolute: true,
            }}
          />
          <Button style={{ marginLeft: 10 }}>
            左侧内容挡住
          </Button>
        </div>
        <h4>使用绝对定位不撑开布局(autoExpandUseAbsolute)</h4>
        <div style={{ height: '40px' }}>
          <Select
           
            style={{ width: 200 }}
            data={options}
            focusAutoExpand
            focusAutoExpandProps={{
              autoExpandUseAbsolute: true,
            }}
          />
          <Button style={{ marginLeft: 10 }}>
            左侧内容挡住
          </Button>
        </div>
      </div>
    );
  }
}

export default SelectDemo;
```

### 允许清除

```jsx
import React, { Component } from 'react';
import { constants, Select, SelectValueType } from '@weapp/ui';

const prefixCls = `${constants.uiPcClsPrefix}-demo-input`;

const options = [
  { id: '1', content: '选项一', other: true, color: '#5D9CEC' },
  { id: '2', content: '选项二', custom: 3, color: '#FF4D4F' },
  {
    id: '3',
    content: '选项三',
    color: '#52C41A',
  },
  { id: '4', content: '禁用项' },
];

class SelectDemo extends Component<any, any> {
  state = {
    value: '1',
    multipleValue: ['1'],
  };
  handleChange = (v: SelectValueType, option: any, event: any) => {
    console.log(v, option, event);
    this.setState({ value: v as string });
  };

  handleMultipleChange = (v: SelectValueType, option: any, event: any) => {
    console.log(v, option, event);
    this.setState({ multipleValue: v as string[] });
  };
  render() {
    const { value, multipleValue } = this.state;
    return (
      <div className={prefixCls}>
        <h4>单选-可清除</h4>
        <Select style={{ width: 200 }} data={options} allowClear />

        <h4>单选-可清除</h4>
        <Select
         
          style={{ width: 200 }}
          value={value}
          data={options}
          allowClear
          onChange={this.handleChange}
        />

        <h4>单选-可取消(allowCancel效果默认去除,默认替换成清除效果)</h4>
        <Select style={{ width: 200 }} data={options} allowCancel />

        <h4>单选-可取消(allowCancel效果默认去除,默认替换成清除效果,受控)</h4>
        <Select
         
          value={value}
          data={options}
          allowCancel
          onChange={this.handleChange}
          style={{ width: 200 }}
        />

        <h4>多选-可清除</h4>
        <Select style={{ width: 200 }} data={options} allowClear multiple />

        <h4>多选-可清除</h4>
        <Select
         
          style={{ width: 200 }}
          data={options}
          value={multipleValue}
          allowClear
          multiple
          onChange={this.handleMultipleChange}
        />
      </div>
    );
  }
}

export default SelectDemo;
```

### 单多选模式

通过multiple、singleAndMultiple属性开启单多选模式。传递的数据项默认为多选,需要设置选项 single为true的时候 为单选选项。

```jsx
import React, { Component } from 'react';
import { constants, Select, SelectOptionData, SelectValueType, SingleType } from '@weapp/ui';
const single = true;
const options = [
  { id: '1', content: '选项一' },
  { id: '2', content: '选项二' },
  { id: '3', content: '选线三' },
  { id: '4', content: '单选一', single },
  { id: '5', content: '单选二', single },
  { id: '6', content: '单选三', single },
];

export default class SelectDemo extends Component {
  state = {
    value: ['1', '2'],
    singleValue: ['4'],
    valueArr: ['1', '2', '3', '4', '5', '6'],
  };
  handleArrChange = (v: SelectValueType) => {
    this.setState({
      value: v,
    });
  };

  handleMutipleChange = (v: SelectValueType) => {
    this.setState({
      valueArr: v,
    });
  };

  handleSingleChange = (v: SelectValueType) => {
    this.setState({
      singleValue: v,
    });
  };

  render() {
    const { value, valueArr, singleValue } = this.state;
    return (
      <div>
        <h4>单多选模式-基本使用(multiple, singleAndMultiple)</h4>
        <Select
         
          data={options}
          style={{ width: 200 }}
          multiple
          singleAndMultiple
        ></Select>

        <h4>单多选模式-可清除(allowClear)</h4>
        <Select
         
          data={options}
          style={{ width: 200 }}
          allowClear
          multiple
          singleAndMultiple
        ></Select>

        <h4>单多选模式-支持全选(allowSelectAll)</h4>
        <Select
         
          data={options}
          style={{ width: 200 }}
          allowClear
          multiple
          allowSelectAll
          singleAndMultiple
        ></Select>

        <h4>单多选模式-受控(默认单选)</h4>
        <Select
         
          data={options}
          style={{ width: 200 }}
          allowClear
          multiple
          singleAndMultiple
          value={singleValue}
          onChange={this.handleSingleChange}
        ></Select>

        <h4>单多选模式-受控(默认多选)</h4>
        <Select
         
          data={options}
          style={{ width: 200 }}
          allowClear
          multiple
          singleAndMultiple
          value={value}
          onChange={this.handleArrChange}
        ></Select>

        <h4>单多选模式-受控(默认传递值包含单多选时,只多选生效)</h4>
        <Select
         
          data={options}
          style={{ width: 200 }}
          allowClear
          multiple
          singleAndMultiple
          value={valueArr}
          onChange={this.handleMutipleChange}
        ></Select>
      </div>
    );
  }
}
```

## API

### 参数说明如下：

| 参数 | 说明 | 类型 | 是否必填 | 默认值 |
| --- | --- | --- | --- | --- |
| value | 当前数(受控值) | string[],SelectOptionsType | F | - |
| defaultValue | 当前数(默认值) | string[],SelectOptionsType | F | - |
| data | 下拉选项数据 | SelectOptionsType | F | - |
| multiple | 是否多选 | boolean | F | false |
| readOnly | 是否只读 | boolean | F | false |
| readOnlyShowPlaceholder | 只读情况下无数据，展示 placeholder | boolean | F | false |
| optionType | 是否显示为标签样式 | boolean | F | false |
| allowSelectAll | 多选时是否允许全选 | boolean | F | false |
| allowCancel | 单选时是否允许取消选中项 | boolean | F | false |
| alwaysTriggerSelect | 单选时允许选中已选数据并触发 onSelect 回调 | F | boolean | false |
| optionType | 选项的类型，可以设置为`'tag'` | string | F | - |
| customOptionRender | 自定义每一选项的渲染 | (option: OptionData) => ReactNode | F | - |
| customInputRender | 自定义输入框的渲染 | (selectComponent:any, selectedData: OptionsType) => ReactNode | F | - |
| tagRender | 自定义标签的渲染 | (props: CustomTagProps) => React.ReactNode | F | - |
| showSearch | 是否可以搜索 | boolean | F | false |
| open | 是否打开下拉框 | boolean | F | false |
| allowClear | 是否可以清除输入框 | boolean | F | false |
| showArrow | 是否显示右侧箭头图标 | boolean | F | false |
| inputIcon | 自定义输入框右侧的图标 | RenderNode | F | - |
| showDataGroupByType | 开启分组功能 | boolean | F | false |
| dataGroupTitle | 分组数据 | DataGroupType | F | false |
| defaultOpen | 是否默认打开下拉框 | boolean | F | false |
| dropdownStyle | 自定义下拉框的样式 | CSSProperties | F | false |
| dropdownClassName | 自定义下拉框的 class | string | F | - |
| dropdownRender | 自定义下拉框 | (menu: React.ReactElement) => React.ReactElement | F | - |
| dropdownMatchSelectWidth | 自定义下拉框宽度，若是 boolean 类型，则与 container 同宽；若是 number，则是自定义宽度 | boolean ｜ number | F | - |
| dropdownPlacement | 自定义下拉框的显示位置 | PopupPlacement | F | - |
| triggerProps | trigger 组件的 props | TriggerConfig | F | - |
| getPopupContainer | 弹层容器定位 | () => HTMLElement ｜ undefined | F | - |
| bindTriggerContainer | 是否绑定弹层容器，若为 true，则调用 getPopupContainer 函数；若为 false，使用 getPopupContainer 这个 props | boolean | F | - |
| disabled | 是否禁用 | boolean | boolean | F |
| filterOption | 自定义筛选，会接收 inputValue option 两个参数，当 option 符合筛选条件时，应返回 true，反之则返回 false | (inputValue: string, option: SelectOptionData) => boolean | F | - |
| onSearch | 搜索数据时触发回调 | (value: string) => void | F | - |
| onSelect | 选择数据时触发回调 | (value: string) => void | SelectOptionData, option: SelectOptionData) => void | F |
| onDeselect | 取消选择数据时触发回调 | SelectOptionData, option: SelectOptionData) => void | F | - |
| onChange | 数据修改时触发回调 | (value: string[],SelectOptionsType, option: SelectOptionData | SelectOptionsType, event: SelectEvent) => void | F |
| onVisibleChange | 下拉框显示隐藏时触发回调 | (visible: boolean) => void | F | - |
| onKeyDown | 按下按键时触发回调 | React.KeyboardEventHandler | F | - |
| onClick | 鼠标点击时触发回调 | React.MouseEventHandler | F | - |
| onFocus | 聚焦输入框时触发回调 | () => void | F | - |
| onBlur | 失去焦点时触发回调 | () => void | F | - |
| onSelectClick | 点击 select 框的回调 | () => void | F | - |
| focusAutoExpand | select 内容区域溢出隐藏情况下,聚焦后自动放大效果功能开关 | boolean | F | - |
| focusAutoExpandProps | select 内容区域隐藏情况下,聚焦后自动放大效果其它参数 | focusAutoExpandProps | F | - |
| customRenderEmpty | 自定义渲染无数据时暂时的空状态 | customRenderEmpty: () => ReactNode | F | - |
| vertical | 是否竖向排列 | boolean | F | - |
#### focusAutoExpandProps 参数说明

**autoExpandUseAbsolute** 是否开启对应 select 组件展开后使用绝对定位，避免撑开布局。默认情况下不设置此属性时候会撑开布局。

**autoExpandParentCls** 对应 select 最大撑开的宽度大小参考系,参考父级 容器 class 类名， 无法直接设置参考容器 可以提供参考容器对应的 class 类名。

**autoExpandContainer** 对应 select 最大撑开的宽度大小参考系,参考父级注 如果不设置对应 select 撑开内容区的宽度参考下 默认效果为视口大小。

```ts
export type focusAutoExpandProps = {
  autoExpandUseAbsolute?: boolean;
  autoExpandParentCls?: string;
  autoExpandContainer?: () => HTMLElement | undefined;
};
```
