fix select

pull/165/head
tangjinzhou 2018-02-11 18:04:31 +08:00
parent cacb5c639d
commit 95a592fdea
7 changed files with 225 additions and 40 deletions

View File

@ -9,7 +9,6 @@ import { hasProp, getSlotOptions } from '../_util/props-util'
import getTransitionProps from '../_util/getTransitionProps'
import { cloneElement, getClass, getPropsData, getValueByProp as getValue, getEvents } from '../_util/vnode'
import BaseMixin from '../_util/BaseMixin'
import {
getPropValue,
getValuePropValue,
@ -62,7 +61,7 @@ export default {
dropdownMenuStyle: PropTypes.object.def({}),
optionFilterProp: SelectPropTypes.optionFilterProp.def('value'),
optionLabelProp: SelectPropTypes.optionLabelProp.def('value'),
notFoundContent: PropTypes.string.def('Not Found'),
notFoundContent: PropTypes.any.def('Not Found'),
backfill: PropTypes.bool.def(false),
showAction: SelectPropTypes.showAction.def(['click']),
combobox: PropTypes.bool.def(false),
@ -83,7 +82,7 @@ export default {
sValue = toArray(defaultValue)
}
sValue = this.addLabelToValue(sValue)
sValue = this.addTitleToValue($slots, sValue)
sValue = this.addTitleToValue($slots.default, sValue)
let inputValue = ''
if (combobox) {
inputValue = sValue.length
@ -115,7 +114,7 @@ export default {
const { combobox, $slots } = this
let value = toArray(this.value)
value = this.addLabelToValue(value)
value = this.addTitleToValue($slots, value)
value = this.addTitleToValue($slots.default, value)
this.setState({
sValue: value,
})
@ -127,9 +126,7 @@ export default {
})
}
}
// this.adjustOpenState()
},
deep: true,
},
},
updated () {
@ -413,7 +410,7 @@ export default {
if (sValue.length) {
this.fireChange([])
}
// this.setOpenState(false, true)
this.setOpenState(false, true)
if (inputValue) {
this.setInputValue('')
}
@ -555,21 +552,51 @@ export default {
},
inputBlur (e) {
this.clearBlurTime()
if (this.disabled) {
return
}
this.blurTimer = setTimeout(() => {
if (!this.disabled) {
this._focused = false
this.setOpenState(false, false)
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)
},
inputFocus (e) {
this.clearBlurTime()
this.clearFocusTime()
this.timeoutFocus()
},
_getInputElement () {
const props = this.$props
const inputElement = props.getInputElement
? props.getInputElement()
: <input id={props.id} autoComplete='off' value='1111'/>
: <input id={props.id} autoComplete='off'/>
const inputCls = classnames(getClass(inputElement), {
[`${props.prefixCls}-search__field`]: true,
})
@ -638,9 +665,9 @@ export default {
return this.$refs.selectTriggerRef.getInnerMenu()
},
setOpenState (open, needFocus, forceSet) {
setOpenState (open, needFocus) {
const { $props: props, openStatus } = this
if (!forceSet && openStatus === open) {
if (openStatus === open) {
this.maybeFocus(open, needFocus)
return
}
@ -785,6 +812,7 @@ export default {
this._focused = true
}
} else {
console.log(activeElement)
if (activeElement !== this.$refs.selectionRef) {
this.$refs.selectionRef.focus()
this._focused = true
@ -810,15 +838,15 @@ export default {
return value
},
addTitleToValue ($slots, values) {
addTitleToValue (children = [], values) {
let nextValues = values
const keys = values.map(v => v.key)
$slots.default.forEach(child => {
children.forEach(child => {
if (!child) {
return
}
if (getSlotOptions(child).isSelectOptGroup) {
nextValues = this.addTitleToValue(child.$slots, nextValues)
nextValues = this.addTitleToValue(child.$slots.default, nextValues)
} else {
const value = getValuePropValue(child)
const valueIndex = keys.indexOf(value)
@ -1048,7 +1076,7 @@ export default {
return options
},
renderFilterOptionsFromChildren (children, childrenKeys, menuItems) {
renderFilterOptionsFromChildren (children = [], childrenKeys, menuItems) {
const sel = []
const props = this.$props
const { inputValue } = this
@ -1320,11 +1348,14 @@ export default {
if (!this.disabled) {
if (this._focused && this.openStatus) {
this._focused = false
this.setOpenState(false, false, true)
this.setOpenState(false, false)
this.getInputDOMNode().blur()
} else {
// this._focused = true
// this.updateFocusClassName()
// this.timeoutFocus()
this._focused = true
this.setOpenState(true, true, true)
this.setOpenState(true, true)
this.getInputDOMNode().focus()
}
}
@ -1338,12 +1369,25 @@ export default {
const { disabled, prefixCls, inputValue, sValue, $listeners } = this
const { mouseenter = noop, mouseleave = noop, popupScroll = noop } = $listeners
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)) {
extraSelectionProps = {
onKeyDown: this.onKeyDown,
tabIndex: props.disabled ? -1 : 0,
}
selectionProps.on.keydown = this.onKeyDown
selectionProps.attrs.tabIndex = props.disabled ? -1 : 0
}
const rootCls = {
[prefixCls]: 1,
@ -1389,22 +1433,9 @@ export default {
ref='rootRef'
// onBlur={this.onOuterBlur}
// onFocus={this.onOuterFocus}
// onClick={this.rootRefClick}
class={classnames(rootCls)}
// tabindex='-1'
>
<div
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}
>
<div {...selectionProps}>
{ctrlNode}
{this.renderClear()}
{multiple || !props.showArrow ? null : (

View File

@ -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>

View File

@ -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>

View File

@ -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)
}

View File

@ -19,7 +19,14 @@ export function getPropValue (child, prop) {
if (prop === 'value') {
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) {

View File

@ -3,7 +3,7 @@ const AsyncComp = () => {
const hashs = window.location.hash.split('/')
const d = hashs[hashs.length - 1]
return {
component: import(`../components/spin/demo/index.vue`),
component: import(`../components/vc-select/demo/${d}.vue`),
}
}
export default [

View File

@ -51,6 +51,7 @@
"highlight.js": "^9.12.0",
"html-webpack-plugin": "^2.30.1",
"istanbul-instrumenter-loader": "^3.0.0",
"jsonp": "^0.2.1",
"karma": "^1.4.1",
"karma-coverage": "^1.1.1",
"karma-coverage-istanbul-reporter": "^1.3.0",
@ -67,6 +68,7 @@
"marked": "^0.3.7",
"mocha": "^3.2.0",
"pre-commit": "^1.2.2",
"querystring": "^0.2.0",
"selenium-server": "^3.0.1",
"semver": "^5.3.0",
"sinon": "^4.0.2",