update select demo
							parent
							
								
									574c5adc98
								
							
						
					
					
						commit
						4ecbecab41
					
				| 
						 | 
				
			
			@ -134,7 +134,7 @@ const VuePropTypes = {
 | 
			
		|||
      // delegate to Vue native prop check
 | 
			
		||||
      return toType('oneOfType', {
 | 
			
		||||
        type: nativeChecks,
 | 
			
		||||
      })
 | 
			
		||||
      }).def(undefined)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const typesStr = arr.map((type) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +153,7 @@ const VuePropTypes = {
 | 
			
		|||
      })
 | 
			
		||||
      if (!valid) warn(`oneOfType - value type should be one of "${typesStr}"`)
 | 
			
		||||
      return valid
 | 
			
		||||
    })
 | 
			
		||||
    }).def(undefined)
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  arrayOf (type) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
<script>
 | 
			
		||||
import Basic from './basic'
 | 
			
		||||
import Size from './size'
 | 
			
		||||
import Tags from './tags'
 | 
			
		||||
import Combobox from './combobox'
 | 
			
		||||
import AutomaticTokenization from './automatic-tokenization'
 | 
			
		||||
import LabelInValue from './label-in-value'
 | 
			
		||||
import Multiple from './multiple'
 | 
			
		||||
import Coordinate from './coordinate'
 | 
			
		||||
import Optgroup from './optgroup'
 | 
			
		||||
import SearchBox from './search-box'
 | 
			
		||||
import Search from './search'
 | 
			
		||||
import SelectUsers from './select-users'
 | 
			
		||||
 | 
			
		||||
import CN from '../index.zh-CN.md'
 | 
			
		||||
import US from '../index.en-US.md'
 | 
			
		||||
const md = {
 | 
			
		||||
  cn: `# Select 选择器
 | 
			
		||||
          下拉选择器。
 | 
			
		||||
          ## 何时使用
 | 
			
		||||
          - 弹出一个下拉菜单给用户选择操作,用于代替原生的选择器,或者需要一个更优雅的多选器时。
 | 
			
		||||
          - 当选项少时(少于 5 项),建议直接将选项平铺,使用 [Radio](/components/radio/) 是更好的选择。
 | 
			
		||||
          ## 代码演示`,
 | 
			
		||||
  us: `# Select
 | 
			
		||||
        Select component to select value from options.
 | 
			
		||||
        ## When To Use
 | 
			
		||||
        - A dropdown menu for displaying choices - an elegant alternative to the native \`<select>\` element.
 | 
			
		||||
        - Utilizing [Radio](/components/radio/) is recommended when there are fewer total options (less than 5).
 | 
			
		||||
        `,
 | 
			
		||||
}
 | 
			
		||||
export default {
 | 
			
		||||
  render () {
 | 
			
		||||
    return (
 | 
			
		||||
      <div>
 | 
			
		||||
        <md cn={md.cn} us={md.us}/>
 | 
			
		||||
        <Basic/>
 | 
			
		||||
        <Size/>
 | 
			
		||||
        <Tags/>
 | 
			
		||||
        <Combobox/>
 | 
			
		||||
        <AutomaticTokenization/>
 | 
			
		||||
        <LabelInValue/>
 | 
			
		||||
        <Multiple/>
 | 
			
		||||
        <Coordinate/>
 | 
			
		||||
        <Optgroup/>
 | 
			
		||||
        <SearchBox/>
 | 
			
		||||
        <Search/>
 | 
			
		||||
        <SelectUsers/>
 | 
			
		||||
        <api>
 | 
			
		||||
          <CN slot='cn' />
 | 
			
		||||
          <US/>
 | 
			
		||||
        </api>
 | 
			
		||||
      </div>
 | 
			
		||||
    )
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
 | 
			
		||||
<cn>
 | 
			
		||||
#### 搜索框
 | 
			
		||||
省市联动是典型的例子。
 | 
			
		||||
自动补全和远程数据结合。
 | 
			
		||||
</cn>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,48 @@
 | 
			
		|||
 | 
			
		||||
<cn>
 | 
			
		||||
#### 带搜索框
 | 
			
		||||
展开后可对选项进行搜索。
 | 
			
		||||
</cn>
 | 
			
		||||
 | 
			
		||||
<us>
 | 
			
		||||
#### Select with search field
 | 
			
		||||
Search the options while expanded.
 | 
			
		||||
</us>
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<template>
 | 
			
		||||
  <a-select
 | 
			
		||||
    showSearch
 | 
			
		||||
    placeholder="Select a person"
 | 
			
		||||
    optionFilterProp="children"
 | 
			
		||||
    style="width: 200px"
 | 
			
		||||
    @focus="handleFocus"
 | 
			
		||||
    @blur="handleBlur"
 | 
			
		||||
    @change="handleChange"
 | 
			
		||||
    :filterOption="filterOption"
 | 
			
		||||
  >
 | 
			
		||||
    <a-select-option value="jack">Jack</a-select-option>
 | 
			
		||||
    <a-select-option value="lucy">Lucy</a-select-option>
 | 
			
		||||
    <a-select-option value="tom">Tom</a-select-option>
 | 
			
		||||
  </a-select>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
  methods: {
 | 
			
		||||
    handleChange (value) {
 | 
			
		||||
      console.log(`selected ${value}`);
 | 
			
		||||
    },
 | 
			
		||||
    handleBlur() {
 | 
			
		||||
      console.log('blur');
 | 
			
		||||
    },
 | 
			
		||||
    handleFocus() {
 | 
			
		||||
      console.log('focus');
 | 
			
		||||
    },
 | 
			
		||||
    filterOption(input, option) {
 | 
			
		||||
      return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,76 @@
 | 
			
		|||
 | 
			
		||||
<cn>
 | 
			
		||||
#### 搜索用户
 | 
			
		||||
一个带有远程搜索,节流控制,请求时序控制,加载状态的多选示例。
 | 
			
		||||
</cn>
 | 
			
		||||
 | 
			
		||||
<us>
 | 
			
		||||
#### Search and Select Users
 | 
			
		||||
A complete multiple select sample with remote search, debounce fetch, ajax callback order flow, and loading state.
 | 
			
		||||
</us>
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<template>
 | 
			
		||||
  <a-select
 | 
			
		||||
    mode="multiple"
 | 
			
		||||
    labelInValue
 | 
			
		||||
    :value="value"
 | 
			
		||||
    placeholder="Select users"
 | 
			
		||||
    style="width: 100%"
 | 
			
		||||
    :filterOption="false"
 | 
			
		||||
    @search="fetchUser"
 | 
			
		||||
    @change="handleChange"
 | 
			
		||||
    :notFoundContent="fetching ? undefined : null"
 | 
			
		||||
  >
 | 
			
		||||
    <a-spin v-if="fetching" slot="notFoundContent" size="small"/>
 | 
			
		||||
    <a-select-option v-for="d in data" :key="d.value">{{d.text}}</a-select-option>
 | 
			
		||||
  </a-select>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import jsonp from 'fetch-jsonp';
 | 
			
		||||
import querystring from 'querystring';
 | 
			
		||||
import debounce from 'lodash.debounce';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  data() {
 | 
			
		||||
    this.lastFetchId = 0;
 | 
			
		||||
    this.fetchUser = debounce(this.fetchUser, 800);
 | 
			
		||||
    return {
 | 
			
		||||
      data: [],
 | 
			
		||||
      value: [],
 | 
			
		||||
      fetching: false,
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    fetchUser (value) {
 | 
			
		||||
      console.log('fetching user', value);
 | 
			
		||||
      this.lastFetchId += 1;
 | 
			
		||||
      const fetchId = this.lastFetchId;
 | 
			
		||||
      this.data = []
 | 
			
		||||
      this.fetching = true
 | 
			
		||||
      fetch('https://randomuser.me/api/?results=5')
 | 
			
		||||
        .then(response => response.json())
 | 
			
		||||
        .then((body) => {
 | 
			
		||||
          if (fetchId !== this.lastFetchId) { // for fetch callback order
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
          const data = body.results.map(user => ({
 | 
			
		||||
            text: `${user.name.first} ${user.name.last}`,
 | 
			
		||||
            value: user.login.username,
 | 
			
		||||
          }));
 | 
			
		||||
          this.data = data
 | 
			
		||||
          this.fetching = false
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
    handleChange (value) {
 | 
			
		||||
      Object.assign(this, {
 | 
			
		||||
        value,
 | 
			
		||||
        data: [],
 | 
			
		||||
        fetching: false,
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,86 @@
 | 
			
		|||
 | 
			
		||||
<cn>
 | 
			
		||||
#### 三种大小
 | 
			
		||||
三种大小的选择框,当 size 分别为 `large` 和 `small` 时,输入框高度为 `40px` 和 `24px` ,默认高度为 `32px`。
 | 
			
		||||
</cn>
 | 
			
		||||
 | 
			
		||||
<us>
 | 
			
		||||
#### Sizes
 | 
			
		||||
The height of the input field for the select defaults to 32px. If size is set to large, the height will be 40px, and if set to small, 24px.
 | 
			
		||||
</us>
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <a-radio-group v-model="size">
 | 
			
		||||
      <a-radio-button value="large">Large</a-radio-button>
 | 
			
		||||
      <a-radio-button value="default">Default</a-radio-button>
 | 
			
		||||
      <a-radio-button value="small">Small</a-radio-button>
 | 
			
		||||
    </a-radio-group>
 | 
			
		||||
    <br /><br />
 | 
			
		||||
    <a-select
 | 
			
		||||
      :size="size"
 | 
			
		||||
      defaultValue="a1"
 | 
			
		||||
      style="width: 200px"
 | 
			
		||||
      @change="handleChange"
 | 
			
		||||
    >
 | 
			
		||||
      <a-select-option v-for="i in 25" :key="(i + 9).toString(36) + i">
 | 
			
		||||
        {{(i + 9).toString(36) + i}}
 | 
			
		||||
      </a-select-option>
 | 
			
		||||
    </a-select>
 | 
			
		||||
    <br />
 | 
			
		||||
    <a-select
 | 
			
		||||
      mode="combobox"
 | 
			
		||||
      :size="size"
 | 
			
		||||
      defaultValue="a1"
 | 
			
		||||
      style="width: 200px"
 | 
			
		||||
      @change="handleChange"
 | 
			
		||||
    >
 | 
			
		||||
      <a-select-option v-for="i in 25" :key="(i + 9).toString(36) + i">
 | 
			
		||||
        {{(i + 9).toString(36) + i}}
 | 
			
		||||
      </a-select-option>
 | 
			
		||||
    </a-select>
 | 
			
		||||
    <br />
 | 
			
		||||
    <a-select
 | 
			
		||||
      mode="multiple"
 | 
			
		||||
      :size="size"
 | 
			
		||||
      placeholder="Please select"
 | 
			
		||||
      :defaultValue="['a1', 'b2']"
 | 
			
		||||
      style="width: 200px"
 | 
			
		||||
      @change="handleChange"
 | 
			
		||||
    >
 | 
			
		||||
      <a-select-option v-for="i in 25" :key="(i + 9).toString(36) + i">
 | 
			
		||||
        {{(i + 9).toString(36) + i}}
 | 
			
		||||
      </a-select-option>
 | 
			
		||||
    </a-select>
 | 
			
		||||
    <br />
 | 
			
		||||
    <a-select
 | 
			
		||||
      mode="tags"
 | 
			
		||||
      :size="size"
 | 
			
		||||
      placeholder="Please select"
 | 
			
		||||
      :defaultValue="['a1', 'b2']"
 | 
			
		||||
      style="width: 200px"
 | 
			
		||||
      @change="handleChange"
 | 
			
		||||
    >
 | 
			
		||||
      <a-select-option v-for="i in 25" :key="(i + 9).toString(36) + i">
 | 
			
		||||
        {{(i + 9).toString(36) + i}}
 | 
			
		||||
      </a-select-option>
 | 
			
		||||
    </a-select>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      size: 'default',
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    handleChange(value) {
 | 
			
		||||
      console.log(`Selected: ${value}`);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
 | 
			
		||||
<cn>
 | 
			
		||||
#### 标签
 | 
			
		||||
tags select,随意输入的内容(scroll the menu)
 | 
			
		||||
</cn>
 | 
			
		||||
 | 
			
		||||
<us>
 | 
			
		||||
#### Tags
 | 
			
		||||
Select with tags, transform input to tag (scroll the menu)
 | 
			
		||||
</us>
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<template>
 | 
			
		||||
  <a-select
 | 
			
		||||
    mode="tags"
 | 
			
		||||
    style="width: 100%"
 | 
			
		||||
    @change="handleChange"
 | 
			
		||||
    placeholder="Tags Mode"
 | 
			
		||||
    @popupScroll="test"
 | 
			
		||||
  >
 | 
			
		||||
    <a-select-option v-for="i in 25" :key="(i + 9).toString(36) + i">{{(i + 9).toString(36) + i}}</a-select-option>
 | 
			
		||||
  </a-select>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
  methods: {
 | 
			
		||||
    handleChange(value) {
 | 
			
		||||
      console.log(`selected ${value}`);
 | 
			
		||||
    },
 | 
			
		||||
    test(e) {
 | 
			
		||||
      console.log(e)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,76 @@
 | 
			
		|||
 | 
			
		||||
## API
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<a-select>
 | 
			
		||||
  <a-select-option value="lucy">lucy</a-select-option>
 | 
			
		||||
</a-select>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Select props
 | 
			
		||||
 | 
			
		||||
| Property | Description | Type | Default |
 | 
			
		||||
| -------- | ----------- | ---- | ------- |
 | 
			
		||||
| allowClear | Show clear button. | boolean | false |
 | 
			
		||||
| autoFocus | Get focus by default | boolean | false |
 | 
			
		||||
| defaultActiveFirstOption | Whether active first option by default | boolean | true |
 | 
			
		||||
| defaultValue | Initial selected option. | string\|number\|string\[]\|number\[] | - |
 | 
			
		||||
| disabled | Whether disabled select | boolean | false |
 | 
			
		||||
| dropdownClassName | className of dropdown menu | string | - |
 | 
			
		||||
| dropdownMatchSelectWidth | Whether dropdown's with is same with select. | boolean | true |
 | 
			
		||||
| dropdownStyle | style of dropdown menu | object | - |
 | 
			
		||||
| filterOption | If true, filter options by input, if function, filter options against it. The function will receive two arguments, `inputValue` and `option`, if the function returns `true`, the option will be included in the filtered set; Otherwise, it will be excluded. | boolean or function(inputValue, option) | true |
 | 
			
		||||
| firstActiveValue | Value of action option by default | string\|string\[] | - |
 | 
			
		||||
| getPopupContainer | Parent Node which the selector should be rendered to. Default to `body`. When position issues happen, try to modify it into scrollable content and position it relative. [Example](https://codesandbox.io/s/4j168r7jw0) | function(triggerNode) | () => document.body |
 | 
			
		||||
| labelInValue | whether to embed label in value, turn the format of value from `string` to `{key: string, label: vNodes}` | boolean | false |
 | 
			
		||||
| maxTagCount | Max tag count to show | number | - |
 | 
			
		||||
| maxTagPlaceholder | Placeholder for not showing tags | slot/function(omittedValues) | - |
 | 
			
		||||
| mode | Set mode of Select | 'multiple' \| 'tags' \| 'combobox' | - |
 | 
			
		||||
| notFoundContent | Specify content to show when no result matches.. | string\|slot | 'Not Found' |
 | 
			
		||||
| optionFilterProp | Which prop value of option will be used for filter if filterOption is true | string | value |
 | 
			
		||||
| optionLabelProp | Which prop value of option will render as content of select. | string | `children` |
 | 
			
		||||
| placeholder | Placeholder of select | string\|slot | - |
 | 
			
		||||
| showSearch | Whether show search input in single mode. | boolean | false |
 | 
			
		||||
| showArrow | Whether to show the drop-down arrow | boolean |  true |
 | 
			
		||||
| size | Size of Select input. `default` `large` `small` | string | default |
 | 
			
		||||
| tokenSeparators | Separator used to tokenize on tag/multiple mode | string\[] |  |
 | 
			
		||||
| value(v-model) | Current selected option. | string\|number\|string\[]\|number\[] | - |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### events
 | 
			
		||||
| Events Name | Description | Arguments |
 | 
			
		||||
| --- | --- | --- |
 | 
			
		||||
| blur | Called when blur | function |
 | 
			
		||||
| change | Called when select an option or input value change, or value of input is changed in combobox mode | function(value, option:Option/Array<Option\>) |
 | 
			
		||||
| deselect | Called when a option is deselected, the params are option's value (or key) . only called for multiple or tags, effective in multiple or tags mode only. | function(value, option:Option) |
 | 
			
		||||
| focus | Called when focus | function |
 | 
			
		||||
| inputKeydown | Called when key pressed | function |
 | 
			
		||||
| mouseenter | Called when mouse enter | function |
 | 
			
		||||
| mouseleave | Called when mouse leave | function |
 | 
			
		||||
| popupScroll | Called when dropdown scrolls | function |
 | 
			
		||||
| search | Callback function that is fired when input changed. | function(value: string) |
 | 
			
		||||
| select | Called when a option is selected, the params are option's value (or key) and option instance. | function(value, option:Option) |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Select Methods
 | 
			
		||||
 | 
			
		||||
| Name | Description |
 | 
			
		||||
| ---- | ----------- |
 | 
			
		||||
| blur() | Remove focus |
 | 
			
		||||
| focus() | Get focus |
 | 
			
		||||
 | 
			
		||||
### Option props
 | 
			
		||||
 | 
			
		||||
| Property | Description | Type | Default |
 | 
			
		||||
| -------- | ----------- | ---- | ------- |
 | 
			
		||||
| disabled | Disable this option | boolean | false |
 | 
			
		||||
| key | Same usage as `value`. If Vue request you to set this property, you can set it to value of option, and then omit value property. | string |  |
 | 
			
		||||
| title | `title` of Select after select this Option | string | - |
 | 
			
		||||
| value | default to filter with this property | string\|number | - |
 | 
			
		||||
 | 
			
		||||
### OptGroup props
 | 
			
		||||
 | 
			
		||||
| Property | Description | Type | Default |
 | 
			
		||||
| -------- | ----------- | ---- | ------- |
 | 
			
		||||
| key |  | string | - |
 | 
			
		||||
| label | Group label | string\|slot | - |
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@ import PropTypes from '../_util/vue-types'
 | 
			
		|||
import VcSelect, { Option, OptGroup } from '../vc-select'
 | 
			
		||||
import LocaleReceiver from '../locale-provider/LocaleReceiver'
 | 
			
		||||
import defaultLocale from '../locale-provider/default'
 | 
			
		||||
import { getComponentFromProp, getOptionProps } from '../_util/props-util'
 | 
			
		||||
import { getComponentFromProp, getOptionProps, filterEmpty } from '../_util/props-util'
 | 
			
		||||
 | 
			
		||||
const AbstractSelectProps = {
 | 
			
		||||
  prefixCls: PropTypes.string,
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ const AbstractSelectProps = {
 | 
			
		|||
  allowClear: PropTypes.bool,
 | 
			
		||||
  disabled: PropTypes.bool,
 | 
			
		||||
  tabIndex: PropTypes.number,
 | 
			
		||||
  placeholder: PropTypes.string,
 | 
			
		||||
  placeholder: PropTypes.any,
 | 
			
		||||
  defaultActiveFirstOption: PropTypes.bool,
 | 
			
		||||
  dropdownClassName: PropTypes.string,
 | 
			
		||||
  dropdownStyle: PropTypes.any,
 | 
			
		||||
| 
						 | 
				
			
			@ -132,6 +132,7 @@ export default {
 | 
			
		|||
          optionLabelProp: optionLabelProp || 'children',
 | 
			
		||||
          notFoundContent: this.getNotFoundContent(locale),
 | 
			
		||||
          maxTagPlaceholder: getComponentFromProp(this, 'maxTagPlaceholder'),
 | 
			
		||||
          placeholder: getComponentFromProp(this, 'placeholder'),
 | 
			
		||||
        },
 | 
			
		||||
        on: this.$listeners,
 | 
			
		||||
        class: cls,
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +141,7 @@ export default {
 | 
			
		|||
 | 
			
		||||
      return (
 | 
			
		||||
        <VcSelect {...selectProps}>
 | 
			
		||||
          {this.$slots.default}
 | 
			
		||||
          {filterEmpty(this.$slots.default)}
 | 
			
		||||
        </VcSelect>
 | 
			
		||||
      )
 | 
			
		||||
    },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,76 @@
 | 
			
		|||
## API
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<a-select>
 | 
			
		||||
  <a-select-option value="lucy">lucy</a-select-option>
 | 
			
		||||
</a-select>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Select props
 | 
			
		||||
 | 
			
		||||
| 参数 | 说明 | 类型 | 默认值 |
 | 
			
		||||
| --- | --- | --- | --- |
 | 
			
		||||
| allowClear | 支持清除 | boolean | false |
 | 
			
		||||
| autoFocus | 默认获取焦点 | boolean | false |
 | 
			
		||||
| defaultActiveFirstOption | 是否默认高亮第一个选项。 | boolean | true |
 | 
			
		||||
| defaultValue | 指定默认选中的条目 | string\|string\[]\|number\|number\[] | - |
 | 
			
		||||
| disabled | 是否禁用 | boolean | false |
 | 
			
		||||
| dropdownClassName | 下拉菜单的 className 属性 | string | - |
 | 
			
		||||
| dropdownMatchSelectWidth | 下拉菜单和选择器同宽 | boolean | true |
 | 
			
		||||
| dropdownStyle | 下拉菜单的 style 属性 | object | - |
 | 
			
		||||
| filterOption | 是否根据输入项进行筛选。当其为一个函数时,会接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 `true`,反之则返回 `false`。 | boolean or function(inputValue, option) | true |
 | 
			
		||||
| firstActiveValue | 默认高亮的选项 | string\|string\[] | - |
 | 
			
		||||
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。[示例](https://codesandbox.io/s/4j168r7jw0) | Function(triggerNode) | () => document.body |
 | 
			
		||||
| labelInValue | 是否把每个选项的 label 包装到 value 中,会把 Select 的 value 类型从 `string` 变为 `{key: string, label: vNodes}` 的格式 | boolean | false |
 | 
			
		||||
| maxTagCount | 最多显示多少个 tag | number | - |
 | 
			
		||||
| maxTagPlaceholder | 隐藏 tag 时显示的内容 | slot/function(omittedValues) | - |
 | 
			
		||||
| mode | 设置 Select 的模式 | 'multiple' \| 'tags' \| 'combobox' | - |
 | 
			
		||||
| notFoundContent | 当下拉列表为空时显示的内容 | string\|slot | 'Not Found' |
 | 
			
		||||
| optionFilterProp | 搜索时过滤对应的 option 属性,如设置为 children 表示对内嵌内容进行搜索 | string | value |
 | 
			
		||||
| optionLabelProp | 回填到选择框的 Option 的属性值,默认是 Option 的子元素。比如在子元素需要高亮效果时,此值可以设为 `value`。 | string | `children` (combobox 模式下为 `value`) |
 | 
			
		||||
| placeholder | 选择框默认文字 | string\|slot | - |
 | 
			
		||||
| showSearch | 使单选模式可搜索 | boolean | false |
 | 
			
		||||
| showArrow | 是否显示下拉小箭头 | boolean |  true |
 | 
			
		||||
| size | 选择框大小,可选 `large` `small` | string | default |
 | 
			
		||||
| tokenSeparators | 在 tags 和 multiple 模式下自动分词的分隔符 | string\[] |  |
 | 
			
		||||
| value(v-model) | 指定当前选中的条目 | string\|string\[]\|number\|number\[] | - |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
> 注意,如果发现下拉菜单跟随页面滚动,或者需要在其他弹层中触发 Select,请尝试使用 `getPopupContainer={triggerNode => triggerNode.parentNode}` 将下拉弹层渲染节点固定在触发器的父元素中。
 | 
			
		||||
 | 
			
		||||
### 事件
 | 
			
		||||
| 事件名称 | 说明 | 回调参数 |
 | 
			
		||||
| --- | --- | --- |
 | 
			
		||||
| blur | 失去焦点的时回调 | function |
 | 
			
		||||
| change | 选中 option,或 input 的 value 变化(combobox 模式下)时,调用此函数 | function(value, option:Option/Array<Option\>) |
 | 
			
		||||
| deselect | 取消选中时调用,参数为选中项的 value (或 key) 值,仅在 multiple 或 tags 模式下生效 | function(value,option:Option) |
 | 
			
		||||
| focus | 获得焦点时回调 | function |
 | 
			
		||||
| inputKeydown | 键盘按下时回调 | function |
 | 
			
		||||
| mouseenter | 鼠标移入时回调 | function |
 | 
			
		||||
| mouseleave | 鼠标移出时回调 | function |
 | 
			
		||||
| popupScroll | 下拉列表滚动时的回调 | function |
 | 
			
		||||
| search | 文本框值变化时回调 | function(value: string) |
 | 
			
		||||
| select | 被选中时调用,参数为选中项的 value (或 key) 值 | function(value, option:Option) |
 | 
			
		||||
 | 
			
		||||
### Select Methods
 | 
			
		||||
 | 
			
		||||
| 名称 | 说明 |
 | 
			
		||||
| --- | --- |
 | 
			
		||||
| blur() | 取消焦点 |
 | 
			
		||||
| focus() | 获取焦点 |
 | 
			
		||||
 | 
			
		||||
### Option props
 | 
			
		||||
 | 
			
		||||
| 参数 | 说明 | 类型 | 默认值 |
 | 
			
		||||
| --- | --- | --- | --- |
 | 
			
		||||
| disabled | 是否禁用 | boolean | false |
 | 
			
		||||
| key | 和 value 含义一致。如果 Vue 需要你设置此项,此项值与 value 的值相同,然后可以省略 value 设置 | string |  |
 | 
			
		||||
| title | 选中该 Option 后,Select 的 title | string | - |
 | 
			
		||||
| value | 默认根据此属性值进行筛选 | string\|number | - |
 | 
			
		||||
 | 
			
		||||
### OptGroup props
 | 
			
		||||
 | 
			
		||||
| 参数 | 说明 | 类型 | 默认值 |
 | 
			
		||||
| --- | --- | --- | --- |
 | 
			
		||||
| key |  | string | - |
 | 
			
		||||
| label | 组名 | string\|\|function(h)\|slot | 无 |
 | 
			
		||||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ import { getSelectKeys, preventDefaultEvent } from './util'
 | 
			
		|||
import { cloneElement } from '../_util/vnode'
 | 
			
		||||
import BaseMixin from '../_util/BaseMixin'
 | 
			
		||||
import { getSlotOptions } from '../_util/props-util'
 | 
			
		||||
import addEventListener from '../_util/Dom/addEventListener'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'DropdownMenu',
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +33,12 @@ export default {
 | 
			
		|||
  mounted () {
 | 
			
		||||
    this.$nextTick(() => {
 | 
			
		||||
      this.scrollActiveItemToView()
 | 
			
		||||
      const { $refs, $listeners } = this
 | 
			
		||||
      if ($listeners.popupScroll) {
 | 
			
		||||
        console.log($refs.menuContainer)
 | 
			
		||||
        this.menuContainerHandler = addEventListener($refs.menuContainer,
 | 
			
		||||
          'scroll', ()=>{console.log(111)})
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    this.lastVisible = this.$props.visible
 | 
			
		||||
  },
 | 
			
		||||
| 
						 | 
				
			
			@ -42,15 +49,12 @@ export default {
 | 
			
		|||
      }
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // shouldComponentUpdate (nextProps) {
 | 
			
		||||
  //   if (!nextProps.visible) {
 | 
			
		||||
  //     this.lastVisible = false
 | 
			
		||||
  //   }
 | 
			
		||||
  //   // freeze when hide
 | 
			
		||||
  //   return nextProps.visible
 | 
			
		||||
  // }
 | 
			
		||||
 | 
			
		||||
  beforeDestroy () {
 | 
			
		||||
    if (this.menuContainerHandler) {
 | 
			
		||||
      this.menuContainerHandler.remove()
 | 
			
		||||
      this.menuContainerHandler = null
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  updated () {
 | 
			
		||||
    const props = this.$props
 | 
			
		||||
    if (!this.prevVisible && props.visible) {
 | 
			
		||||
| 
						 | 
				
			
			@ -170,13 +174,13 @@ export default {
 | 
			
		|||
  render () {
 | 
			
		||||
    const renderMenu = this.renderMenu()
 | 
			
		||||
    this.prevVisible = this.visible
 | 
			
		||||
    const { popupFocus, popupScroll } = this.$listeners
 | 
			
		||||
    const { popupFocus } = this.$listeners
 | 
			
		||||
    return renderMenu ? (
 | 
			
		||||
      <div
 | 
			
		||||
        style={{ overflow: 'auto' }}
 | 
			
		||||
        onFocus={popupFocus}
 | 
			
		||||
        onMousedown={preventDefaultEvent}
 | 
			
		||||
        onScroll={popupScroll}
 | 
			
		||||
        ref='menuContainer'
 | 
			
		||||
      >
 | 
			
		||||
        {renderMenu}
 | 
			
		||||
      </div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -141,7 +141,16 @@ export default {
 | 
			
		|||
        })
 | 
			
		||||
      }
 | 
			
		||||
      this.sValue = sValue
 | 
			
		||||
      this.initLabelAndTitleMap()
 | 
			
		||||
 | 
			
		||||
      sValue.forEach((val) => {
 | 
			
		||||
        const key = val.key
 | 
			
		||||
        let { label, title } = val
 | 
			
		||||
        label = label === undefined ? this.labelMap.get(key) : label
 | 
			
		||||
        title = title === undefined ? this.titleMap.get(key) : title
 | 
			
		||||
        this.labelMap.set(key, label === undefined ? key : label)
 | 
			
		||||
        this.titleMap.set(key, title)
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      if (this.combobox) {
 | 
			
		||||
        this.setState({
 | 
			
		||||
          inputValue: sValue.length ? this.labelMap.get((sValue[0].key)) : '',
 | 
			
		||||
| 
						 | 
				
			
			@ -382,68 +391,68 @@ export default {
 | 
			
		|||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onOuterFocus (e) {
 | 
			
		||||
      if (this.disabled) {
 | 
			
		||||
        e.preventDefault()
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      this.clearBlurTime()
 | 
			
		||||
      if (
 | 
			
		||||
        !isMultipleOrTagsOrCombobox(this.$props) &&
 | 
			
		||||
      e.target === this.getInputDOMNode()
 | 
			
		||||
      ) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      if (this._focused) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      this._focused = true
 | 
			
		||||
      this.updateFocusClassName()
 | 
			
		||||
      this.timeoutFocus()
 | 
			
		||||
    },
 | 
			
		||||
    // onOuterFocus (e) {
 | 
			
		||||
    //   if (this.disabled) {
 | 
			
		||||
    //     e.preventDefault()
 | 
			
		||||
    //     return
 | 
			
		||||
    //   }
 | 
			
		||||
    //   this.clearBlurTime()
 | 
			
		||||
    //   if (
 | 
			
		||||
    //     !isMultipleOrTagsOrCombobox(this.$props) &&
 | 
			
		||||
    //   e.target === this.getInputDOMNode()
 | 
			
		||||
    //   ) {
 | 
			
		||||
    //     return
 | 
			
		||||
    //   }
 | 
			
		||||
    //   if (this._focused) {
 | 
			
		||||
    //     return
 | 
			
		||||
    //   }
 | 
			
		||||
    //   this._focused = true
 | 
			
		||||
    //   this.updateFocusClassName()
 | 
			
		||||
    //   this.timeoutFocus()
 | 
			
		||||
    // },
 | 
			
		||||
 | 
			
		||||
    onPopupFocus () {
 | 
			
		||||
    // fix ie scrollbar, focus element again
 | 
			
		||||
      this.maybeFocus(true, true)
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onOuterBlur (e) {
 | 
			
		||||
      if (this.disabled) {
 | 
			
		||||
        e.preventDefault()
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      this.blurTimer = setTimeout(() => {
 | 
			
		||||
        this._focused = false
 | 
			
		||||
        this.updateFocusClassName()
 | 
			
		||||
        const props = this.$props
 | 
			
		||||
        let { sValue } = this
 | 
			
		||||
        const { inputValue } = this
 | 
			
		||||
        if (
 | 
			
		||||
          isSingleMode(props) &&
 | 
			
		||||
        props.showSearch &&
 | 
			
		||||
        inputValue &&
 | 
			
		||||
        props.defaultActiveFirstOption
 | 
			
		||||
        ) {
 | 
			
		||||
          const options = this._options || []
 | 
			
		||||
          if (options.length) {
 | 
			
		||||
            const firstOption = findFirstMenuItem(options)
 | 
			
		||||
            if (firstOption) {
 | 
			
		||||
              sValue = [
 | 
			
		||||
                {
 | 
			
		||||
                  key: firstOption.key,
 | 
			
		||||
                  label: this.getLabelFromOption(firstOption),
 | 
			
		||||
                },
 | 
			
		||||
              ]
 | 
			
		||||
              this.fireChange(sValue)
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        } else if (isMultipleOrTags(props) && inputValue) {
 | 
			
		||||
          this.inputValue = this.getInputDOMNode().value = ''
 | 
			
		||||
        }
 | 
			
		||||
        this.$emit('blur', this.getVLForOnChange(sValue))
 | 
			
		||||
        this.setOpenState(false)
 | 
			
		||||
      }, 10)
 | 
			
		||||
    },
 | 
			
		||||
    // onOuterBlur (e) {
 | 
			
		||||
    //   if (this.disabled) {
 | 
			
		||||
    //     e.preventDefault()
 | 
			
		||||
    //     return
 | 
			
		||||
    //   }
 | 
			
		||||
    //   this.blurTimer = setTimeout(() => {
 | 
			
		||||
    //     this._focused = false
 | 
			
		||||
    //     this.updateFocusClassName()
 | 
			
		||||
    //     const props = this.$props
 | 
			
		||||
    //     let { sValue } = this
 | 
			
		||||
    //     const { inputValue } = this
 | 
			
		||||
    //     if (
 | 
			
		||||
    //       isSingleMode(props) &&
 | 
			
		||||
    //     props.showSearch &&
 | 
			
		||||
    //     inputValue &&
 | 
			
		||||
    //     props.defaultActiveFirstOption
 | 
			
		||||
    //     ) {
 | 
			
		||||
    //       const options = this._options || []
 | 
			
		||||
    //       if (options.length) {
 | 
			
		||||
    //         const firstOption = findFirstMenuItem(options)
 | 
			
		||||
    //         if (firstOption) {
 | 
			
		||||
    //           sValue = [
 | 
			
		||||
    //             {
 | 
			
		||||
    //               key: firstOption.key,
 | 
			
		||||
    //               label: this.getLabelFromOption(firstOption),
 | 
			
		||||
    //             },
 | 
			
		||||
    //           ]
 | 
			
		||||
    //           this.fireChange(sValue)
 | 
			
		||||
    //         }
 | 
			
		||||
    //       }
 | 
			
		||||
    //     } else if (isMultipleOrTags(props) && inputValue) {
 | 
			
		||||
    //       this.inputValue = this.getInputDOMNode().value = ''
 | 
			
		||||
    //     }
 | 
			
		||||
    //     this.$emit('blur', this.getVLForOnChange(sValue))
 | 
			
		||||
    //     this.setOpenState(false)
 | 
			
		||||
    //   }, 10)
 | 
			
		||||
    // },
 | 
			
		||||
 | 
			
		||||
    onClearSelection (event) {
 | 
			
		||||
      const { inputValue, sValue, disabled } = this
 | 
			
		||||
| 
						 | 
				
			
			@ -524,8 +533,7 @@ export default {
 | 
			
		|||
      }
 | 
			
		||||
      return this.getOptionsFromChildren(value, this.$slots.default)
 | 
			
		||||
    },
 | 
			
		||||
    getLabelBySingleValue (children, value) {
 | 
			
		||||
      console.log('getLabelBySingleValue')
 | 
			
		||||
    getLabelBySingleValue (children = [], value) {
 | 
			
		||||
      if (value === undefined) {
 | 
			
		||||
        return null
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -546,7 +554,7 @@ export default {
 | 
			
		|||
      return label
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getValueByLabel (children, label) {
 | 
			
		||||
    getValueByLabel (children = [], label) {
 | 
			
		||||
      if (label === undefined) {
 | 
			
		||||
        return null
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -852,7 +860,6 @@ export default {
 | 
			
		|||
      } else {
 | 
			
		||||
        filterFn = defaultFilter
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!filterFn) {
 | 
			
		||||
        return true
 | 
			
		||||
      } else if (typeof filterFn === 'function') {
 | 
			
		||||
| 
						 | 
				
			
			@ -1010,7 +1017,7 @@ export default {
 | 
			
		|||
    },
 | 
			
		||||
 | 
			
		||||
    isChildDisabled (key) {
 | 
			
		||||
      return this.$slots.default.some(child => {
 | 
			
		||||
      return (this.$slots.default || []).some(child => {
 | 
			
		||||
        const childValue = getValuePropValue(child)
 | 
			
		||||
        return childValue === key && getValue(child, 'disabled')
 | 
			
		||||
      })
 | 
			
		||||
| 
						 | 
				
			
			@ -1420,19 +1427,19 @@ export default {
 | 
			
		|||
      }
 | 
			
		||||
      return null
 | 
			
		||||
    },
 | 
			
		||||
    rootRefClick (e) {
 | 
			
		||||
      // e.stopPropagation()
 | 
			
		||||
      if (this._focused) {
 | 
			
		||||
        // this.getInputDOMNode().blur()
 | 
			
		||||
        this.onOuterBlur()
 | 
			
		||||
      } else {
 | 
			
		||||
        this.onOuterFocus()
 | 
			
		||||
        // this.getInputDOMNode().focus()
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    // rootRefClick (e) {
 | 
			
		||||
    //   // e.stopPropagation()
 | 
			
		||||
    //   if (this._focused) {
 | 
			
		||||
    //     // this.getInputDOMNode().blur()
 | 
			
		||||
    //     this.onOuterBlur()
 | 
			
		||||
    //   } else {
 | 
			
		||||
    //     this.onOuterFocus()
 | 
			
		||||
    //     // this.getInputDOMNode().focus()
 | 
			
		||||
    //   }
 | 
			
		||||
    // },
 | 
			
		||||
    selectionRefClick (e) {
 | 
			
		||||
      console.log('selectionRefClick')
 | 
			
		||||
      e.stopPropagation()
 | 
			
		||||
      this.clearBlurTime()
 | 
			
		||||
      if (!this.disabled) {
 | 
			
		||||
        const input = this.getInputDOMNode()
 | 
			
		||||
        if (this._focused && this.openStatus) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1440,9 +1447,7 @@ export default {
 | 
			
		|||
          this.setOpenState(false, false)
 | 
			
		||||
          input && input.blur()
 | 
			
		||||
        } else {
 | 
			
		||||
          // this._focused = true
 | 
			
		||||
          // this.updateFocusClassName()
 | 
			
		||||
          // this.timeoutFocus()
 | 
			
		||||
          this.clearBlurTime()
 | 
			
		||||
          this._focused = true
 | 
			
		||||
          this.setOpenState(true, true)
 | 
			
		||||
          input && input.focus()
 | 
			
		||||
| 
						 | 
				
			
			@ -1450,12 +1455,16 @@ export default {
 | 
			
		|||
      }
 | 
			
		||||
    },
 | 
			
		||||
    selectionRefFocus (e) {
 | 
			
		||||
      if (this._focused) {
 | 
			
		||||
      if (this._focused || this.disabled) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      this._focused = true
 | 
			
		||||
      this.updateFocusClassName()
 | 
			
		||||
    },
 | 
			
		||||
    selectionRefBlur (e) {
 | 
			
		||||
      this._focused = false
 | 
			
		||||
      this.updateFocusClassName()
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  render () {
 | 
			
		||||
| 
						 | 
				
			
			@ -1486,10 +1495,11 @@ export default {
 | 
			
		|||
    if (!isMultipleOrTagsOrCombobox(props)) {
 | 
			
		||||
      selectionProps.on.keydown = this.onKeyDown
 | 
			
		||||
      selectionProps.on.focus = this.selectionRefFocus
 | 
			
		||||
      selectionProps.on.blur = this.selectionRefBlur
 | 
			
		||||
      selectionProps.attrs.tabIndex = props.disabled ? -1 : 0
 | 
			
		||||
    }
 | 
			
		||||
    const rootCls = {
 | 
			
		||||
      [prefixCls]: 1,
 | 
			
		||||
      [prefixCls]: true,
 | 
			
		||||
      [`${prefixCls}-open`]: openStatus,
 | 
			
		||||
      [`${prefixCls}-focused`]: openStatus || !!this._focused,
 | 
			
		||||
      [`${prefixCls}-combobox`]: isCombobox(props),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -141,6 +141,7 @@ export default {
 | 
			
		|||
      getPopupContainer,
 | 
			
		||||
      showAction,
 | 
			
		||||
    } = $props
 | 
			
		||||
    const { mouseenter, mouseleave, popupFocus, dropdownVisibleChange } = $listeners
 | 
			
		||||
    const dropdownPrefixCls = this.getDropdownPrefixCls()
 | 
			
		||||
    const popupClassName = {
 | 
			
		||||
      [dropdownClassName]: !!dropdownClassName,
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +154,7 @@ export default {
 | 
			
		|||
        inputValue,
 | 
			
		||||
        visible,
 | 
			
		||||
      }, on: {
 | 
			
		||||
        popupFocus: $listeners.popupFocus,
 | 
			
		||||
        popupFocus,
 | 
			
		||||
      },
 | 
			
		||||
    })
 | 
			
		||||
    let hideAction
 | 
			
		||||
| 
						 | 
				
			
			@ -186,10 +187,16 @@ export default {
 | 
			
		|||
        popupStyle,
 | 
			
		||||
      },
 | 
			
		||||
      on: {
 | 
			
		||||
        popupVisibleChange: $listeners.dropdownVisibleChange,
 | 
			
		||||
        popupVisibleChange: dropdownVisibleChange,
 | 
			
		||||
      },
 | 
			
		||||
      ref: 'triggerRef',
 | 
			
		||||
    }
 | 
			
		||||
    if (mouseenter) {
 | 
			
		||||
      triggerProps.on.mouseenter = mouseenter
 | 
			
		||||
    }
 | 
			
		||||
    if (mouseleave) {
 | 
			
		||||
      triggerProps.on.mouseleave = mouseleave
 | 
			
		||||
    }
 | 
			
		||||
    return (
 | 
			
		||||
      <Trigger {...triggerProps}>
 | 
			
		||||
        {$slots.default}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue