fix select

pull/9/head
tjz 2018-02-07 23:03:47 +08:00
parent ce7f9850dd
commit eaaa0a1bab
8 changed files with 131 additions and 86 deletions

View File

@ -17,8 +17,12 @@ const filterProps = (props, propsData = {}) => {
}) })
return res return res
} }
const getSlotOptions = (slot) => { const getSlotOptions = (ele) => {
return slot.componentOptions.Ctor.options let componentOptions = ele.componentOptions
if (ele.$vnode) {
componentOptions = ele.$vnode.componentOptions
}
return componentOptions.Ctor.options
} }
const getOptionProps = (instance) => { const getOptionProps = (instance) => {
const { $options = {}, $props = {}} = instance const { $options = {}, $props = {}} = instance
@ -35,8 +39,18 @@ const getComponentFromProp = (instance, prop) => {
} }
const getPropsData = (ele) => { const getPropsData = (ele) => {
return ele.componentOptions && ele.componentOptions.propsData let componentOptions = ele.componentOptions
if (ele.$vnode) {
componentOptions = ele.$vnode.componentOptions
}
return componentOptions && componentOptions.propsData
} }
const getKey = (ele) => {
export { hasProp, filterProps, getOptionProps, getComponentFromProp, getSlotOptions, slotHasProp, getPropsData } let key = ele.key
if (ele.$vnode) {
key = ele.$vnode.key
}
return key
}
export { hasProp, filterProps, getOptionProps, getComponentFromProp, getSlotOptions, slotHasProp, getPropsData, getKey }
export default hasProp export default hasProp

View File

@ -87,7 +87,7 @@ export default {
if (!transitionName) { if (!transitionName) {
if (typeof animation === 'string') { if (typeof animation === 'string') {
transitionName = `${animation}` transitionName = `${animation}`
} else if (animation.props && animation.props.name) { } else if (animation && animation.props && animation.props.name) {
transitionName = animation.props.name transitionName = animation.props.name
} }
} }

View File

@ -51,9 +51,8 @@ export default {
// } // }
updated () { updated () {
const prevProps = this.prevProps
const props = this.$props const props = this.$props
if (!prevProps.visible && props.visible) { if (!this.prevVisible && props.visible) {
this.$nextTick(() => { this.$nextTick(() => {
this.scrollActiveItemToView() this.scrollActiveItemToView()
}) })
@ -64,7 +63,7 @@ export default {
methods: { methods: {
scrollActiveItemToView () { scrollActiveItemToView () {
// scroll into view // scroll into view
const itemComponent = this.$refs.firstActiveItem.$el const itemComponent = this.$refs.firstActiveItem && this.$refs.firstActiveItem.$el
const props = this.$props const props = this.$props
if (itemComponent) { if (itemComponent) {
@ -170,6 +169,7 @@ export default {
}, },
render () { render () {
const renderMenu = this.renderMenu() const renderMenu = this.renderMenu()
this.prevVisible = this.visible
const { popupFocus, popupScroll } = this.$listeners const { popupFocus, popupScroll } = this.$listeners
return renderMenu ? ( return renderMenu ? (
<div <div

View File

@ -65,6 +65,7 @@ export default {
notFoundContent: PropTypes.string.def('Not Found'), notFoundContent: PropTypes.string.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),
// onChange: noop, // onChange: noop,
// onFocus: noop, // onFocus: noop,
// onBlur: noop, // onBlur: noop,
@ -105,26 +106,30 @@ export default {
this.autoFocus && this.focus() this.autoFocus && this.focus()
}) })
}, },
beforeUpdate () { watch: {
if (hasProp(this, 'value')) { '$props': {
const { combobox, $slots } = this handler: function (nextProps) {
let value = toArray(this.value) if (hasProp(this, 'value')) {
value = this.addLabelToValue(value) const { combobox, $slots } = this
value = this.addTitleToValue($slots, value) let value = toArray(this.value)
this.setState({ value = this.addLabelToValue(value)
sValue: value, value = this.addTitleToValue($slots, value)
}) this.setState({
if (combobox) { sValue: value,
this.setState({ })
inputValue: value.length if (combobox) {
? this.getLabelFromProps(value[0].key) this.setState({
: '', inputValue: value.length
}) ? this.getLabelFromProps(value[0].key)
} : '',
} })
this.adjustOpenState() }
}
this.adjustOpenState()
},
deep: true,
},
}, },
updated () { updated () {
this.$nextTick(() => { this.$nextTick(() => {
if (isMultipleOrTags(this.$props)) { if (isMultipleOrTags(this.$props)) {
@ -259,7 +264,7 @@ export default {
} }
} }
this.__emit('select', event, item) this.__emit('select', event, item)
const selectedTitle = item.props.title const selectedTitle = item.title
if (isMultipleOrTags(props)) { if (isMultipleOrTags(props)) {
if (findIndexInValueByKey(sValue, selectedValue) !== -1) { if (findIndexInValueByKey(sValue, selectedValue) !== -1) {
return return
@ -416,7 +421,6 @@ export default {
if (!child) { if (!child) {
return return
} }
console.log('child', child)
if (getSlotOptions(child).isSelectOptGroup) { if (getSlotOptions(child).isSelectOptGroup) {
const maybe = this.getLabelBySingleValue(child.componentOptions.children, value) const maybe = this.getLabelBySingleValue(child.componentOptions.children, value)
if (maybe !== null) { if (maybe !== null) {
@ -501,17 +505,23 @@ export default {
hidden = false hidden = false
} }
if (placeholder) { if (placeholder) {
const p = {
props: {
},
on: {
mousedown: preventDefaultEvent,
click: this.onPlaceholderClick,
},
attrs: UNSELECTABLE_ATTRIBUTE,
style: {
display: hidden ? 'none' : 'block',
...UNSELECTABLE_STYLE,
},
class: `${prefixCls}-selection__placeholder`,
}
return ( return (
<div <div {...p}>
onMousedown={preventDefaultEvent}
style={{
display: hidden ? 'none' : 'block',
...UNSELECTABLE_STYLE,
}}
{...UNSELECTABLE_ATTRIBUTE}
onClick={this.onPlaceholderClick}
class={`${prefixCls}-selection__placeholder`}
>
{placeholder} {placeholder}
</div> </div>
) )
@ -540,8 +550,8 @@ export default {
class: inputCls, class: inputCls,
ref: 'inputRef', ref: 'inputRef',
on: { on: {
change: this.onInputChange, input: this.onInputChange,
keyDown: chaining( keydown: chaining(
this.onInputKeydown, this.onInputKeydown,
getEvents(inputElement).keydown || noop, getEvents(inputElement).keydown || noop,
this.$listeners.inputKeydown this.$listeners.inputKeydown
@ -611,7 +621,7 @@ export default {
}, },
focus () { focus () {
if (isSingleMode(this.props)) { if (isSingleMode(this.$props)) {
this.$refs.selectionRef.focus() this.$refs.selectionRef.focus()
} else { } else {
this.getInputDOMNode().focus() this.getInputDOMNode().focus()
@ -619,7 +629,7 @@ export default {
}, },
blur () { blur () {
if (isSingleMode(this.props)) { if (isSingleMode(this.$props)) {
this.$refs.selectionRef.blur() this.$refs.selectionRef.blur()
} else { } else {
this.getInputDOMNode().blur() this.getInputDOMNode().blur()
@ -717,7 +727,7 @@ export default {
if (needFocus || open) { if (needFocus || open) {
const input = this.getInputDOMNode() const input = this.getInputDOMNode()
const { activeElement } = document const { activeElement } = document
if (input && (open || isMultipleOrTagsOrCombobox(this.props))) { if (input && (open || isMultipleOrTagsOrCombobox(this.$props))) {
if (activeElement !== input) { if (activeElement !== input) {
input.focus() input.focus()
this._focused = true this._focused = true
@ -890,7 +900,7 @@ export default {
const menuItem = ( const menuItem = (
<MenuItem <MenuItem
style={UNSELECTABLE_STYLE} style={UNSELECTABLE_STYLE}
attribute={UNSELECTABLE_ATTRIBUTE} {...{ attrs: UNSELECTABLE_ATTRIBUTE }}
value={key} value={key}
key={key} key={key}
> >
@ -917,13 +927,16 @@ export default {
return !filterFn() return !filterFn()
}) })
if (notFindInputItem) { if (notFindInputItem) {
const p = {
attrs: UNSELECTABLE_ATTRIBUTE,
key: inputValue,
props: {
value: inputValue,
},
style: UNSELECTABLE_STYLE,
}
options.unshift( options.unshift(
<MenuItem <MenuItem {...p}>
style={UNSELECTABLE_STYLE}
attribute={UNSELECTABLE_ATTRIBUTE}
value={inputValue}
key={inputValue}
>
{inputValue} {inputValue}
</MenuItem> </MenuItem>
) )
@ -932,14 +945,17 @@ export default {
} }
if (!options.length && notFoundContent) { if (!options.length && notFoundContent) {
const p = {
attrs: UNSELECTABLE_ATTRIBUTE,
key: 'NOT_FOUND',
props: {
value: 'NOT_FOUND',
disabled: true,
},
style: UNSELECTABLE_STYLE,
}
options = [ options = [
<MenuItem <MenuItem {...p}>
style={UNSELECTABLE_STYLE}
attribute={UNSELECTABLE_ATTRIBUTE}
disabled
value='NOT_FOUND'
key='NOT_FOUND'
>
{notFoundContent} {notFoundContent}
</MenuItem>, </MenuItem>,
] ]
@ -978,11 +994,10 @@ export default {
} }
return return
} }
warning( warning(
getSlotOptions(child).isSelectOptGroup, getSlotOptions(child).isSelectOption,
'the children of `Select` should be `Select.Option` or `Select.OptGroup`, ' + 'the children of `Select` should be `Select.Option` or `Select.OptGroup`, ' +
`instead of \`${getSlotOptions(child).isSelectOptGroup || `instead of \`${getSlotOptions(child).name ||
getSlotOptions(child)}\`.` getSlotOptions(child)}\`.`
) )
@ -991,14 +1006,18 @@ export default {
validateOptionValue(childValue, this.$props) validateOptionValue(childValue, this.$props)
if (this._filterOption(inputValue, child)) { if (this._filterOption(inputValue, child)) {
const p = {
attrs: UNSELECTABLE_ATTRIBUTE,
key: childValue,
props: {
value: childValue,
...getPropsData(child),
},
style: UNSELECTABLE_STYLE,
on: getEvents(child),
}
const menuItem = ( const menuItem = (
<MenuItem <MenuItem {...p}>{child.componentOptions.children}</MenuItem>
style={UNSELECTABLE_STYLE}
attribute={UNSELECTABLE_ATTRIBUTE}
value={childValue}
key={childValue}
{...getPropsData(child)}
/>
) )
sel.push(menuItem) sel.push(menuItem)
menuItems.push(menuItem) menuItems.push(menuItem)
@ -1086,8 +1105,8 @@ export default {
} }
maxTagPlaceholderEl = (<li maxTagPlaceholderEl = (<li
style={UNSELECTABLE_STYLE} style={UNSELECTABLE_STYLE}
{...UNSELECTABLE_ATTRIBUTE} unselectable='unselectable'
onMouseDown={preventDefaultEvent} onMousedown={preventDefaultEvent}
class={`${prefixCls}-selection__choice ${prefixCls}-selection__choice__disabled`} class={`${prefixCls}-selection__choice ${prefixCls}-selection__choice__disabled`}
key={'maxTagPlaceholder'} key={'maxTagPlaceholder'}
title={content} title={content}
@ -1113,7 +1132,7 @@ export default {
return ( return (
<li <li
style={UNSELECTABLE_STYLE} style={UNSELECTABLE_STYLE}
{...UNSELECTABLE_ATTRIBUTE} unselectable='unselectable'
onMousedown={preventDefaultEvent} onMousedown={preventDefaultEvent}
class={choiceClassName} class={choiceClassName}
key={singleValue.key} key={singleValue.key}
@ -1146,6 +1165,7 @@ export default {
if (isMultipleOrTags(props) && choiceTransitionName) { if (isMultipleOrTags(props) && choiceTransitionName) {
const transitionProps = getTransitionProps(choiceTransitionName, { const transitionProps = getTransitionProps(choiceTransitionName, {
tag: 'ul', tag: 'ul',
afterLeave: this.onChoiceAnimationLeave,
}) })
innerNode = ( innerNode = (
<transition-group <transition-group
@ -1180,7 +1200,7 @@ export default {
key='clear' key='clear'
onMousedown={preventDefaultEvent} onMousedown={preventDefaultEvent}
style={UNSELECTABLE_STYLE} style={UNSELECTABLE_STYLE}
{...UNSELECTABLE_ATTRIBUTE} unselectable='unselectable'
class={`${prefixCls}-selection__clear`} class={`${prefixCls}-selection__clear`}
onClick={this.onClearSelection} onClick={this.onClearSelection}
/> />
@ -1279,7 +1299,7 @@ export default {
key='arrow' key='arrow'
class={`${prefixCls}-arrow`} class={`${prefixCls}-arrow`}
style={UNSELECTABLE_STYLE} style={UNSELECTABLE_STYLE}
{...UNSELECTABLE_ATTRIBUTE} unselectable='unselectable'
onClick={this.onArrowClick} onClick={this.onArrowClick}
> >
<b /> <b />

View File

@ -32,17 +32,21 @@ export default {
// onPopupFocus: PropTypes.func, // onPopupFocus: PropTypes.func,
// onPopupScroll: PropTypes.func, // onPopupScroll: PropTypes.func,
dropdownMatchSelectWidth: PropTypes.bool, dropdownMatchSelectWidth: PropTypes.bool,
defaultActiveFirstOption: PropTypes.bool,
dropdownAlign: PropTypes.object, dropdownAlign: PropTypes.object,
visible: PropTypes.bool, visible: PropTypes.bool,
disabled: PropTypes.bool, disabled: PropTypes.bool,
showSearch: PropTypes.bool, showSearch: PropTypes.bool,
dropdownClassName: PropTypes.string, dropdownClassName: PropTypes.string,
dropdownStyle: PropTypes.object,
dropdownMenuStyle: PropTypes.object,
multiple: PropTypes.bool, multiple: PropTypes.bool,
inputValue: PropTypes.string, inputValue: PropTypes.string,
filterOption: PropTypes.any, filterOption: PropTypes.any,
options: PropTypes.any, options: PropTypes.any,
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
popupClassName: PropTypes.string, popupClassName: PropTypes.string,
value: PropTypes.array,
// children: PropTypes.any, // children: PropTypes.any,
showAction: PropTypes.arrayOf(PropTypes.string), showAction: PropTypes.arrayOf(PropTypes.string),
}, },

View File

@ -35,10 +35,10 @@ export default {
<p> <p>
<button onClick={this.toggleDisabled}>toggle disabled</button> <button onClick={this.toggleDisabled}>toggle disabled</button>
</p> </p>
<div style={{ width: 300 }}> <div style={{ width: '300px' }}>
<Select <Select
disabled={this.disabled} disabled={this.disabled}
style={{ width: 500 }} style={{ width: '500px' }}
onChange={this.onChange} onChange={this.onChange}
onSelect={this.onSelect} onSelect={this.onSelect}
onInputKeydown={this.onKeyDown} onInputKeydown={this.onKeyDown}

View File

@ -1,11 +1,11 @@
import { getPropsData, getSlotOptions } from '../_util/props-util' import { getPropsData, getSlotOptions, getKey } from '../_util/props-util'
export function getValuePropValue (child) { export function getValuePropValue (child) {
const props = getPropsData(child) const props = getPropsData(child)
if ('value' in props) { if ('value' in props) {
return props.value return props.value
} }
if (child.key) { if (getKey(child)) {
return child.key return getKey(child)
} }
if (getSlotOptions(child).isSelectOptGroup && props.label) { if (getSlotOptions(child).isSelectOptGroup && props.label) {
return props.label return props.label
@ -84,9 +84,9 @@ export function getSelectKeys (menuItems, value) {
} }
let selectedKeys = [] let selectedKeys = []
menuItems.forEach(item => { menuItems.forEach(item => {
if (item.type.isMenuItemGroup) { if (getSlotOptions(item).isMenuItemGroup) {
selectedKeys = selectedKeys.concat( selectedKeys = selectedKeys.concat(
getSelectKeys(item.props.children, value) getSelectKeys(item.componentOptions.children, value)
) )
} else { } else {
const itemValue = getValuePropValue(item) const itemValue = getValuePropValue(item)
@ -111,12 +111,13 @@ export const UNSELECTABLE_ATTRIBUTE = {
export function findFirstMenuItem (children) { export function findFirstMenuItem (children) {
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
const child = children[i] const child = children[i]
if (child.type.isMenuItemGroup) { const props = getSlotOptions(child)
const found = findFirstMenuItem(child.props.children) if (props.isMenuItemGroup) {
const found = findFirstMenuItem(child.componentOptions.children)
if (found) { if (found) {
return found return found
} }
} else if (!child.props.disabled) { } else if (!props.disabled) {
return child return child
} }
} }
@ -138,10 +139,11 @@ export function splitBySeparators (string, separators) {
} }
export function defaultFilterFn (input, child) { export function defaultFilterFn (input, child) {
if (child.props.disabled) { const props = getSlotOptions(child)
if (props.disabled) {
return false return false
} }
const value = String(getPropValue(child, this.props.optionFilterProp)) const value = String(getPropValue(child, this.optionFilterProp))
return ( return (
value.toLowerCase().indexOf(input.toLowerCase()) > -1 value.toLowerCase().indexOf(input.toLowerCase()) > -1
) )

5
package-lock.json generated
View File

@ -2051,6 +2051,11 @@
} }
} }
}, },
"classnames": {
"version": "2.2.5",
"resolved": "http://registry.npm.taobao.org/classnames/download/classnames-2.2.5.tgz",
"integrity": "sha1-+zgB1FNGdknvNgPH1hoCvRKb3m0="
},
"clean-css": { "clean-css": {
"version": "4.1.9", "version": "4.1.9",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.9.tgz", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.9.tgz",