fix select
							parent
							
								
									832d13eb0c
								
							
						
					
					
						commit
						c44c425a67
					
				|  | @ -9,7 +9,6 @@ import { hasProp, getSlotOptions } from '../_util/props-util' | ||||||
| import getTransitionProps from '../_util/getTransitionProps' | import getTransitionProps from '../_util/getTransitionProps' | ||||||
| import { cloneElement, getClass, getPropsData, getValueByProp as getValue, getEvents } from '../_util/vnode' | import { cloneElement, getClass, getPropsData, getValueByProp as getValue, getEvents } from '../_util/vnode' | ||||||
| import BaseMixin from '../_util/BaseMixin' | import BaseMixin from '../_util/BaseMixin' | ||||||
| 
 |  | ||||||
| import { | import { | ||||||
|   getPropValue, |   getPropValue, | ||||||
|   getValuePropValue, |   getValuePropValue, | ||||||
|  | @ -62,7 +61,7 @@ export default { | ||||||
|     dropdownMenuStyle: PropTypes.object.def({}), |     dropdownMenuStyle: PropTypes.object.def({}), | ||||||
|     optionFilterProp: SelectPropTypes.optionFilterProp.def('value'), |     optionFilterProp: SelectPropTypes.optionFilterProp.def('value'), | ||||||
|     optionLabelProp: SelectPropTypes.optionLabelProp.def('value'), |     optionLabelProp: SelectPropTypes.optionLabelProp.def('value'), | ||||||
|     notFoundContent: PropTypes.string.def('Not Found'), |     notFoundContent: PropTypes.any.def('Not Found'), | ||||||
|     backfill: PropTypes.bool.def(false), |     backfill: PropTypes.bool.def(false), | ||||||
|     showAction: SelectPropTypes.showAction.def(['click']), |     showAction: SelectPropTypes.showAction.def(['click']), | ||||||
|     combobox: PropTypes.bool.def(false), |     combobox: PropTypes.bool.def(false), | ||||||
|  | @ -83,7 +82,7 @@ export default { | ||||||
|       sValue = toArray(defaultValue) |       sValue = toArray(defaultValue) | ||||||
|     } |     } | ||||||
|     sValue = this.addLabelToValue(sValue) |     sValue = this.addLabelToValue(sValue) | ||||||
|     sValue = this.addTitleToValue($slots, sValue) |     sValue = this.addTitleToValue($slots.default, sValue) | ||||||
|     let inputValue = '' |     let inputValue = '' | ||||||
|     if (combobox) { |     if (combobox) { | ||||||
|       inputValue = sValue.length |       inputValue = sValue.length | ||||||
|  | @ -115,7 +114,7 @@ export default { | ||||||
|           const { combobox, $slots } = this |           const { combobox, $slots } = this | ||||||
|           let value = toArray(this.value) |           let value = toArray(this.value) | ||||||
|           value = this.addLabelToValue(value) |           value = this.addLabelToValue(value) | ||||||
|           value = this.addTitleToValue($slots, value) |           value = this.addTitleToValue($slots.default, value) | ||||||
|           this.setState({ |           this.setState({ | ||||||
|             sValue: value, |             sValue: value, | ||||||
|           }) |           }) | ||||||
|  | @ -127,9 +126,7 @@ export default { | ||||||
|             }) |             }) | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         // this.adjustOpenState() |  | ||||||
|       }, |       }, | ||||||
|       deep: true, |  | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|   updated () { |   updated () { | ||||||
|  | @ -413,7 +410,7 @@ export default { | ||||||
|         if (sValue.length) { |         if (sValue.length) { | ||||||
|           this.fireChange([]) |           this.fireChange([]) | ||||||
|         } |         } | ||||||
|         // this.setOpenState(false, true) |         this.setOpenState(false, true) | ||||||
|         if (inputValue) { |         if (inputValue) { | ||||||
|           this.setInputValue('') |           this.setInputValue('') | ||||||
|         } |         } | ||||||
|  | @ -555,21 +552,51 @@ export default { | ||||||
|     }, |     }, | ||||||
|     inputBlur (e) { |     inputBlur (e) { | ||||||
|       this.clearBlurTime() |       this.clearBlurTime() | ||||||
|  |       if (this.disabled) { | ||||||
|  |         return | ||||||
|  |       } | ||||||
|       this.blurTimer = setTimeout(() => { |       this.blurTimer = setTimeout(() => { | ||||||
|         if (!this.disabled) { |         this._focused = false | ||||||
|           this._focused = false |         this.updateFocusClassName() | ||||||
|           this.setOpenState(false, false) |         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) |       }, 10) | ||||||
|     }, |     }, | ||||||
|     inputFocus (e) { |     inputFocus (e) { | ||||||
|       this.clearBlurTime() |       this.clearBlurTime() | ||||||
|  |       this.clearFocusTime() | ||||||
|  |       this.timeoutFocus() | ||||||
|     }, |     }, | ||||||
|     _getInputElement () { |     _getInputElement () { | ||||||
|       const props = this.$props |       const props = this.$props | ||||||
|       const inputElement = props.getInputElement |       const inputElement = props.getInputElement | ||||||
|         ? props.getInputElement() |         ? props.getInputElement() | ||||||
|         : <input id={props.id} autoComplete='off' value='1111'/> |         : <input id={props.id} autoComplete='off'/> | ||||||
|       const inputCls = classnames(getClass(inputElement), { |       const inputCls = classnames(getClass(inputElement), { | ||||||
|         [`${props.prefixCls}-search__field`]: true, |         [`${props.prefixCls}-search__field`]: true, | ||||||
|       }) |       }) | ||||||
|  | @ -638,9 +665,9 @@ export default { | ||||||
|       return this.$refs.selectTriggerRef.getInnerMenu() |       return this.$refs.selectTriggerRef.getInnerMenu() | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|     setOpenState (open, needFocus, forceSet) { |     setOpenState (open, needFocus) { | ||||||
|       const { $props: props, openStatus } = this |       const { $props: props, openStatus } = this | ||||||
|       if (!forceSet && openStatus === open) { |       if (openStatus === open) { | ||||||
|         this.maybeFocus(open, needFocus) |         this.maybeFocus(open, needFocus) | ||||||
|         return |         return | ||||||
|       } |       } | ||||||
|  | @ -785,6 +812,7 @@ export default { | ||||||
|             this._focused = true |             this._focused = true | ||||||
|           } |           } | ||||||
|         } else { |         } else { | ||||||
|  |           console.log(activeElement) | ||||||
|           if (activeElement !== this.$refs.selectionRef) { |           if (activeElement !== this.$refs.selectionRef) { | ||||||
|             this.$refs.selectionRef.focus() |             this.$refs.selectionRef.focus() | ||||||
|             this._focused = true |             this._focused = true | ||||||
|  | @ -810,15 +838,15 @@ export default { | ||||||
|       return value |       return value | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|     addTitleToValue ($slots, values) { |     addTitleToValue (children = [], values) { | ||||||
|       let nextValues = values |       let nextValues = values | ||||||
|       const keys = values.map(v => v.key) |       const keys = values.map(v => v.key) | ||||||
|       $slots.default.forEach(child => { |       children.forEach(child => { | ||||||
|         if (!child) { |         if (!child) { | ||||||
|           return |           return | ||||||
|         } |         } | ||||||
|         if (getSlotOptions(child).isSelectOptGroup) { |         if (getSlotOptions(child).isSelectOptGroup) { | ||||||
|           nextValues = this.addTitleToValue(child.$slots, nextValues) |           nextValues = this.addTitleToValue(child.$slots.default, nextValues) | ||||||
|         } else { |         } else { | ||||||
|           const value = getValuePropValue(child) |           const value = getValuePropValue(child) | ||||||
|           const valueIndex = keys.indexOf(value) |           const valueIndex = keys.indexOf(value) | ||||||
|  | @ -1048,7 +1076,7 @@ export default { | ||||||
|       return options |       return options | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|     renderFilterOptionsFromChildren (children, childrenKeys, menuItems) { |     renderFilterOptionsFromChildren (children = [], childrenKeys, menuItems) { | ||||||
|       const sel = [] |       const sel = [] | ||||||
|       const props = this.$props |       const props = this.$props | ||||||
|       const { inputValue } = this |       const { inputValue } = this | ||||||
|  | @ -1320,11 +1348,14 @@ export default { | ||||||
|       if (!this.disabled) { |       if (!this.disabled) { | ||||||
|         if (this._focused && this.openStatus) { |         if (this._focused && this.openStatus) { | ||||||
|           this._focused = false |           this._focused = false | ||||||
|           this.setOpenState(false, false, true) |           this.setOpenState(false, false) | ||||||
|           this.getInputDOMNode().blur() |           this.getInputDOMNode().blur() | ||||||
|         } else { |         } else { | ||||||
|  |           // this._focused = true | ||||||
|  |           // this.updateFocusClassName() | ||||||
|  |           // this.timeoutFocus() | ||||||
|           this._focused = true |           this._focused = true | ||||||
|           this.setOpenState(true, true, true) |           this.setOpenState(true, true) | ||||||
|           this.getInputDOMNode().focus() |           this.getInputDOMNode().focus() | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  | @ -1338,12 +1369,25 @@ export default { | ||||||
|     const { disabled, prefixCls, inputValue, sValue, $listeners } = this |     const { disabled, prefixCls, inputValue, sValue, $listeners } = this | ||||||
|     const { mouseenter = noop, mouseleave = noop, popupScroll = noop } = $listeners |     const { mouseenter = noop, mouseleave = noop, popupScroll = noop } = $listeners | ||||||
|     const ctrlNode = this.renderTopControlNode(openStatus) |     const ctrlNode = this.renderTopControlNode(openStatus) | ||||||
|     let extraSelectionProps = {} |     const selectionProps = { | ||||||
|  |       props: {}, | ||||||
|  |       attrs: { | ||||||
|  |         role: 'combobox', | ||||||
|  |         'aria-autocomplete': 'list', | ||||||
|  |         'aria-haspopup': 'true', | ||||||
|  |         'aria-expanded': openStatus.toString(), | ||||||
|  |       }, | ||||||
|  |       on: { | ||||||
|  |         click: this.selectionRefClick, | ||||||
|  |       }, | ||||||
|  |       class: `${prefixCls}-selection ${prefixCls}-selection--${multiple ? 'multiple' : 'single'}`, | ||||||
|  |       ref: 'selectionRef', | ||||||
|  |       key: 'selection', | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|     if (!isMultipleOrTagsOrCombobox(props)) { |     if (!isMultipleOrTagsOrCombobox(props)) { | ||||||
|       extraSelectionProps = { |       selectionProps.on.keydown = this.onKeyDown | ||||||
|         onKeyDown: this.onKeyDown, |       selectionProps.attrs.tabIndex = props.disabled ? -1 : 0 | ||||||
|         tabIndex: props.disabled ? -1 : 0, |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|     const rootCls = { |     const rootCls = { | ||||||
|       [prefixCls]: 1, |       [prefixCls]: 1, | ||||||
|  | @ -1389,22 +1433,9 @@ export default { | ||||||
|           ref='rootRef' |           ref='rootRef' | ||||||
|           // onBlur={this.onOuterBlur} |           // onBlur={this.onOuterBlur} | ||||||
|           // onFocus={this.onOuterFocus} |           // onFocus={this.onOuterFocus} | ||||||
|           // onClick={this.rootRefClick} |  | ||||||
|           class={classnames(rootCls)} |           class={classnames(rootCls)} | ||||||
|           // tabindex='-1' |  | ||||||
|         > |         > | ||||||
|           <div |           <div {...selectionProps}> | ||||||
|             ref='selectionRef' |  | ||||||
|             key='selection' |  | ||||||
|             class={`${prefixCls}-selection |  | ||||||
|             ${prefixCls}-selection--${multiple ? 'multiple' : 'single'}`} |  | ||||||
|             role='combobox' |  | ||||||
|             aria-autocomplete='list' |  | ||||||
|             aria-haspopup='true' |  | ||||||
|             aria-expanded={openStatus} |  | ||||||
|             {...extraSelectionProps} |  | ||||||
|             onClick={this.selectionRefClick} |  | ||||||
|           > |  | ||||||
|             {ctrlNode} |             {ctrlNode} | ||||||
|             {this.renderClear()} |             {this.renderClear()} | ||||||
|             {multiple || !props.showArrow ? null : ( |             {multiple || !props.showArrow ? null : ( | ||||||
|  |  | ||||||
|  | @ -0,0 +1,46 @@ | ||||||
|  | <script> | ||||||
|  | import Select, { Option } from '../index' | ||||||
|  | import '../assets/index.less' | ||||||
|  | 
 | ||||||
|  | export default { | ||||||
|  |   data () { | ||||||
|  |     return { | ||||||
|  |       disabled: false, | ||||||
|  |       options: [], | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   methods: { | ||||||
|  |     onChange (value) { | ||||||
|  |       console.log('onChange', value) | ||||||
|  |       let options = [] | ||||||
|  |       if (value) { | ||||||
|  |         if (value.indexOf('@') >= 0) { | ||||||
|  |           options = <Option key={value}>{value}</Option> | ||||||
|  |         } else { | ||||||
|  |           options = ['gmail.com', 'yahoo.com', 'outlook.com'].map((domain) => { | ||||||
|  |             const email = `${value}@${domain}` | ||||||
|  |             return <Option key={email}>{email}</Option> | ||||||
|  |           }) | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       this.options = options | ||||||
|  |     }, | ||||||
|  |     onSelect (v) { | ||||||
|  |       console.log('onSelect', v) | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   render () { | ||||||
|  |     return (<Select | ||||||
|  |       combobox | ||||||
|  |       notFoundContent={false} | ||||||
|  |       style='width: 200px' | ||||||
|  |       onChange={this.onChange} | ||||||
|  |       onSelect={this.onSelect} | ||||||
|  |       placeholder='请输入账户名' | ||||||
|  |     > | ||||||
|  |       {this.options} | ||||||
|  |     </Select>) | ||||||
|  |   }, | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | @ -0,0 +1,64 @@ | ||||||
|  | <script> | ||||||
|  | import Select, { Option } from '../index' | ||||||
|  | import { fetch } from './tbFetchSuggest' | ||||||
|  | import '../assets/index.less' | ||||||
|  | 
 | ||||||
|  | export default { | ||||||
|  |   data () { | ||||||
|  |     return { | ||||||
|  |       disabled: false, | ||||||
|  |       data: [], | ||||||
|  |       value: undefined, | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   methods: { | ||||||
|  |     onChange (value) { | ||||||
|  |       console.log('select ', value) | ||||||
|  |       // value.label = value.key | ||||||
|  |       this.value = value | ||||||
|  |     }, | ||||||
|  |     fetchData (value) { | ||||||
|  |       if (value) { | ||||||
|  |         fetch(value, (data) => { | ||||||
|  |           this.data = data | ||||||
|  |         }) | ||||||
|  |       } else { | ||||||
|  |         this.data = [] | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     toggleDisabled () { | ||||||
|  |       this.disabled = !this.disabled | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   render () { | ||||||
|  |     const data = this.data | ||||||
|  |     const options = data.map((d) => { | ||||||
|  |       return <Option key={d.value}><i>{d.text}</i></Option> | ||||||
|  |     }) | ||||||
|  |     return (<div> | ||||||
|  |       <h2>force suggest</h2> | ||||||
|  |       <p> | ||||||
|  |         <button onClick={this.toggleDisabled}>toggle disabled</button> | ||||||
|  |       </p> | ||||||
|  |       <div> | ||||||
|  |         <Select | ||||||
|  |           labelInValue | ||||||
|  |           onSearch={this.fetchData} | ||||||
|  |           disabled={this.disabled} | ||||||
|  |           value={this.value} | ||||||
|  |           optionLabelProp='children' | ||||||
|  |           placeholder='placeholder' | ||||||
|  |           defaultActiveFirstOption | ||||||
|  |           style={{ width: '500px' }} | ||||||
|  |           onChange={this.onChange} | ||||||
|  |           filterOption={false} | ||||||
|  |         > | ||||||
|  |           {options} | ||||||
|  |         </Select> | ||||||
|  |       </div> | ||||||
|  |     </div>) | ||||||
|  |   }, | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | @ -0,0 +1,35 @@ | ||||||
|  | 
 | ||||||
|  | import jsonp from 'jsonp' | ||||||
|  | import querystring from 'querystring' | ||||||
|  | let timeout | ||||||
|  | let currentValue | ||||||
|  | 
 | ||||||
|  | export function fetch (value, callback) { | ||||||
|  |   if (timeout) { | ||||||
|  |     clearTimeout(timeout) | ||||||
|  |     timeout = null | ||||||
|  |   } | ||||||
|  |   currentValue = value | ||||||
|  | 
 | ||||||
|  |   function fake () { | ||||||
|  |     const str = querystring.encode({ | ||||||
|  |       code: 'utf-8', | ||||||
|  |       q: value, | ||||||
|  |     }) | ||||||
|  |     jsonp(`http://suggest.taobao.com/sug?${str}`, (err, d) => { // eslint-disable-line
 | ||||||
|  |       if (currentValue === value) { | ||||||
|  |         const result = d.result | ||||||
|  |         const data = [] | ||||||
|  |         result.forEach((r) => { | ||||||
|  |           data.push({ | ||||||
|  |             value: r[0], | ||||||
|  |             text: r[0], | ||||||
|  |           }) | ||||||
|  |         }) | ||||||
|  |         callback(data) | ||||||
|  |       } | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   timeout = setTimeout(fake, 300) | ||||||
|  | } | ||||||
|  | @ -19,7 +19,14 @@ export function getPropValue (child, prop) { | ||||||
|   if (prop === 'value') { |   if (prop === 'value') { | ||||||
|     return getValuePropValue(child) |     return getValuePropValue(child) | ||||||
|   } |   } | ||||||
|   return child.props[prop] |   if (prop === 'children') { | ||||||
|  |     if (child.$slots) { | ||||||
|  |       return child.$slots.default | ||||||
|  |     } else { | ||||||
|  |       return child.componentOptions.children | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return getPropsData(child)[prop] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function isMultiple (props) { | export function isMultiple (props) { | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ const AsyncComp = () => { | ||||||
|   const hashs = window.location.hash.split('/') |   const hashs = window.location.hash.split('/') | ||||||
|   const d = hashs[hashs.length - 1] |   const d = hashs[hashs.length - 1] | ||||||
|   return { |   return { | ||||||
|     component: import(`../components/spin/demo/index.vue`), |     component: import(`../components/vc-select/demo/${d}.vue`), | ||||||
|   } |   } | ||||||
| } | } | ||||||
| export default [ | export default [ | ||||||
|  |  | ||||||
|  | @ -51,6 +51,7 @@ | ||||||
|     "highlight.js": "^9.12.0", |     "highlight.js": "^9.12.0", | ||||||
|     "html-webpack-plugin": "^2.30.1", |     "html-webpack-plugin": "^2.30.1", | ||||||
|     "istanbul-instrumenter-loader": "^3.0.0", |     "istanbul-instrumenter-loader": "^3.0.0", | ||||||
|  |     "jsonp": "^0.2.1", | ||||||
|     "karma": "^1.4.1", |     "karma": "^1.4.1", | ||||||
|     "karma-coverage": "^1.1.1", |     "karma-coverage": "^1.1.1", | ||||||
|     "karma-coverage-istanbul-reporter": "^1.3.0", |     "karma-coverage-istanbul-reporter": "^1.3.0", | ||||||
|  | @ -67,6 +68,7 @@ | ||||||
|     "marked": "^0.3.7", |     "marked": "^0.3.7", | ||||||
|     "mocha": "^3.2.0", |     "mocha": "^3.2.0", | ||||||
|     "pre-commit": "^1.2.2", |     "pre-commit": "^1.2.2", | ||||||
|  |     "querystring": "^0.2.0", | ||||||
|     "selenium-server": "^3.0.1", |     "selenium-server": "^3.0.1", | ||||||
|     "semver": "^5.3.0", |     "semver": "^5.3.0", | ||||||
|     "sinon": "^4.0.2", |     "sinon": "^4.0.2", | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 tangjinzhou
						tangjinzhou