add select demo

This commit is contained in:
tangjinzhou 2018-02-12 18:10:51 +08:00
parent c0f892c002
commit 5dcc6678fa
12 changed files with 389 additions and 45 deletions

View File

@ -22,7 +22,7 @@ const getSlotOptions = (ele) => {
if (ele.$vnode) {
componentOptions = ele.$vnode.componentOptions
}
return componentOptions.Ctor.options
return componentOptions ? componentOptions.Ctor.options || {} : {}
}
const getOptionProps = (instance) => {
const { $options = {}, $props = {}} = instance
@ -43,8 +43,17 @@ const getPropsData = (ele) => {
if (ele.$vnode) {
componentOptions = ele.$vnode.componentOptions
}
return componentOptions && componentOptions.propsData
return componentOptions ? componentOptions.propsData || {} : {}
}
const getAttrs = (ele) => {
let data = ele.data
if (ele.$vnode) {
data = ele.$vnode.data
}
return data ? data.attrs || {} : {}
}
const getKey = (ele) => {
let key = ele.key
if (ele.$vnode) {
@ -52,5 +61,15 @@ const getKey = (ele) => {
}
return key
}
export { hasProp, filterProps, getOptionProps, getComponentFromProp, getSlotOptions, slotHasProp, getPropsData, getKey }
export {
hasProp,
filterProps,
getOptionProps,
getComponentFromProp,
getSlotOptions,
slotHasProp,
getPropsData,
getKey,
getAttrs,
}
export default hasProp

View File

@ -128,7 +128,7 @@ export function getPropsData (ele) {
return ele.componentOptions && ele.componentOptions.propsData
}
export function getValueByProp (ele, prop) {
return ele.componentOptions && ele.componentOptions.propsData[prop]
return ele.componentOptions && ele.componentOptions.propsData && ele.componentOptions.propsData[prop]
}
export function getEvents (child) {

View File

@ -1,5 +1,9 @@
<script>
import PropTypes from '../_util/vue-types'
export default {
props: {
label: PropTypes.any,
},
isSelectOptGroup: true,
}
</script>

View File

@ -8,6 +8,7 @@ export default {
PropTypes.number,
]),
disabled: PropTypes.bool,
title: PropTypes.string,
},
isSelectOption: true,
}

View File

@ -113,25 +113,32 @@ export default {
})
},
watch: {
'$props': {
handler: function (nextProps) {
if (hasProp(this, 'value')) {
const { combobox, $slots } = this
let value = toArray(this.value)
value = this.addLabelToValue(value)
value = this.addTitleToValue($slots.default, value)
this.setState({
sValue: value,
})
if (combobox) {
this.setState({
inputValue: value.length
? this.getLabelFromProps(value[0].key)
: '',
})
}
}
},
// '$props': {
// handler: function (nextProps) {
// if (hasProp(this, 'value')) {
// console.log('nextProps', nextProps)
// const { combobox, $slots } = this
// let value = toArray(this.value)
// value = this.addLabelToValue(value)
// value = this.addTitleToValue($slots.default, value)
// this.setState({
// sValue: value,
// })
// if (combobox) {
// this.setState({
// inputValue: value.length
// ? this.getLabelFromProps(value[0].key)
// : '',
// })
// }
// }
// },
// },
value (val) {
this.updateState()
},
combobox () {
this.updateState()
},
},
updated () {
@ -148,10 +155,6 @@ export default {
}
})
},
beforeUpdate () {
// console.log('beforeUpdate')
// this.adjustOpenState()
},
beforeDestroy () {
this.clearFocusTime()
this.clearBlurTime()
@ -163,6 +166,22 @@ export default {
}
},
methods: {
updateState () {
const { combobox, $slots } = this
let value = toArray(this.value)
value = this.addLabelToValue(value)
value = this.addTitleToValue($slots.default, value)
this.setState({
sValue: value,
})
if (combobox) {
this.setState({
inputValue: value.length
? this.getLabelFromProps(value[0].key)
: '',
})
}
},
onInputChange (event) {
const { tokenSeparators } = this
const val = event.target.value
@ -437,7 +456,7 @@ export default {
},
onChoiceAnimationLeave () {
this.$refs.selectTriggerRef.triggerRef.forcePopupAlign()
this.$refs.selectTriggerRef.$refs.triggerRef.forcePopupAlign()
},
getOptionsFromChildren (value, children = [], options = []) {
let values = value
@ -535,6 +554,7 @@ export default {
},
getLabelFromOption (child) {
console.log(child, this.optionLabelProp)
return getPropValue(child, this.optionLabelProp)
},
@ -635,14 +655,12 @@ export default {
if (options.length) {
const firstOption = findFirstMenuItem(options)
if (firstOption) {
console.log('pre', this.sValue)
sValue = [
{
key: firstOption.key,
label: this.getLabelFromOption(firstOption),
},
]
console.log('new', this.sValue, sValue)
this.fireChange(sValue)
}
}
@ -833,6 +851,8 @@ export default {
this.clearFocusTime()
}
this.focusTimer = setTimeout(() => {
this._focused = true
this.updateFocusClassName()
this.__emit('focus')
}, 10)
},
@ -911,7 +931,7 @@ export default {
return
}
if (getSlotOptions(child).isSelectOptGroup) {
nextValues = this.addTitleToValue(child.$slots.default, nextValues)
nextValues = this.addTitleToValue(child.componentOptions.children, nextValues)
} else {
const value = getValuePropValue(child)
const valueIndex = keys.indexOf(value)
@ -961,7 +981,7 @@ export default {
this.__emit('select', labelInValue ? value : value.key, this.getSingleOptionByValueKey(value.key))
},
fireChange (value) {
if (hasProp(this, 'value')) {
if (!hasProp(this, 'value')) {
this.setState({
sValue: value,
})
@ -975,7 +995,7 @@ export default {
isChildDisabled (key) {
return this.$slots.default.some(child => {
const childValue = getValuePropValue(child)
return childValue === key && getValue(child, 'title')
return childValue === key && getValue(child, 'disabled')
})
},
@ -1304,6 +1324,7 @@ export default {
}
if (isMultipleOrTags(props)) {
selectedValueNodes = limitedCountValue.map(singleValue => {
console.log('singleValue', singleValue)
let content = singleValue.label
const title = singleValue.title || content
if (
@ -1353,29 +1374,25 @@ export default {
if (isMultipleOrTags(props) && choiceTransitionName) {
const transitionProps = getTransitionProps(choiceTransitionName, {
tag: 'ul',
// beforeEnter: this.onChoiceAnimationLeave,
afterLeave: this.onChoiceAnimationLeave,
})
innerNode = (
<transition-group
// onLeave={this.onChoiceAnimationLeave}
// component='ul'
// transitionName={choiceTransitionName}
{...transitionProps}
onClick={this.muitipleContainerClick}
>
{selectedValueNodes}
</transition-group>
)
} else {
innerNode = (
<ul onClick={this.muitipleContainerClick}>
<ul>
{selectedValueNodes}
</ul>
)
}
}
return (
<div class={className} ref='topCtrlRef'>
<div class={className} ref='topCtrlRef' onClick={this.muitipleContainerClick}>
{this.getPlaceholderElement()}
{innerNode}
</div>
@ -1426,17 +1443,18 @@ export default {
e.stopPropagation()
this.clearBlurTime()
if (!this.disabled) {
const input = this.getInputDOMNode()
if (this._focused && this.openStatus) {
this._focused = false
this.setOpenState(false, false)
this.getInputDOMNode().blur()
input && input.blur()
} else {
// this._focused = true
// this.updateFocusClassName()
// this.timeoutFocus()
this._focused = true
this.setOpenState(true, true)
this.getInputDOMNode().focus()
input && input.focus()
}
}
},

View File

@ -0,0 +1,56 @@
<script>
import Select, { Option } from '../index'
import '../assets/index.less'
import { fetch } from './tbFetchSuggest'
export default {
data () {
return {
data: [],
value: [],
}
},
methods: {
onChange (value) {
console.log('onChange ', value)
this.value = value
},
onSelect (value) {
console.log('select ', value)
},
fetchData (value) {
fetch(value, (data) => {
this.data = data
})
},
},
render () {
const data = this.data
const options = data.map((d) => {
return <Option key={d.value}><i>{d.text}</i></Option>
})
return (<div>
<h2>multiple suggest</h2>
<div>
<Select
style={{ width: '500px' }}
labelInValue
optionLabelProp='children'
value={this.value}
onChange={this.onChange}
tags
placeholder='placeholder'
notFoundContent=''
onSearch={this.fetchData}
onSelect={this.onSelect}
filterOption={false}
>
{options}
</Select>
</div>
</div>)
},
}
</script>

View File

@ -0,0 +1,58 @@
<script>
import Select, { Option } from '../index'
import '../assets/index.less'
import { fetch } from './tbFetchSuggest'
export default {
data () {
return {
data: [],
value: ['b11'],
}
},
methods: {
onChange (value) {
console.log('onChange ', value)
this.value = value
},
onSelect (value) {
console.log('select ', value)
},
fetchData (value) {
fetch(value, (data) => {
this.data = data
})
},
},
render () {
const children = []
for (let i = 10; i < 36; i++) {
// 11 => readonly selected item
children.push(<Option disabled={i === 11} key={i.toString(36) + i}>中文{i}</Option>)
}
const dropdownMenuStyle = {
maxHeight: '200px',
}
return (<div>
<h2>multiple readonly default selected item</h2>
<div>
<Select
multiple
value={this.value}
animation='slide-up'
choiceTransitionName='rc-select-selection__choice-zoom'
dropdownMenuStyle={dropdownMenuStyle}
style={{ width: '500px' }}
optionFilterProp='children'
optionLabelProp='children'
placeholder='please select'
onChange={this.onChange}
>
{children}
</Select>
</div>
</div>)
},
}
</script>

View File

@ -0,0 +1,74 @@
<script>
import Select, { Option } from '../index'
import '../assets/index.less'
export default {
data () {
return {
useAnim: 0,
value: ['a10'],
}
},
methods: {
onChange (value, options) {
console.log('onChange', value, options)
this.value = value
},
onSelect (...args) {
console.log('select ', args)
},
onDeselect (...args) {
console.log('deselect ', args)
},
useAnimation (e) {
this.useAnim = e.target.checked
},
},
render () {
const children = []
for (let i = 10; i < 36; i++) {
children.push(
<Option key={i.toString(36) + i} disabled={i === 10} title={`中文${i}`}>
中文{i}
</Option>
)
}
const dropdownMenuStyle = {
maxHeight: '200px',
}
return (<div>
<h2>multiple selectscroll the menu</h2>
<p>
<label>
anim
<input checked={this.useAnim} type='checkbox' onChange={this.useAnimation} />
</label>
</p>
<div style={{ width: '300px' }}>
<Select
value={this.value}
animation={this.useAnim ? 'slide-up' : null}
choiceTransitionName='rc-select-selection__choice-zoom'
dropdownMenuStyle={dropdownMenuStyle}
style={{ width: '500px' }}
multiple
allowClear
optionFilterProp='children'
optionLabelProp='children'
onSelect={this.onSelect}
onDeselect={this.onDeselect}
placeholder='please select'
onChange={this.onChange}
onFocus={() => console.log('focus')}
tokenSeparators={[' ', ',']}
>
{children}
</Select>
</div>
</div>)
},
}
</script>

View File

@ -0,0 +1,43 @@
<script>
import Select, { Option, OptGroup } from '../index'
import '../assets/index.less'
export default {
methods: {
onChange (value, options) {
console.log(`selected ${value}`)
},
},
render () {
return (<div>
<h2>Select OptGroup</h2>
<div style={{ width: '300px' }}>
<Select
placeholder='placeholder'
defaultValue='lucy'
showSearch={false}
style={{ width: '500px' }}
onChange={this.onChange}
>
<OptGroup label='manager'>
<Option value='jack'>
<b
style={{
color: 'red',
}}
>
jack
</b>
</Option>
<Option value='lucy'>lucy</Option>
</OptGroup>
<OptGroup label='engineer'>
<Option value='yiminghe'>yiminghe</Option>
</OptGroup>
</Select>
</div>
</div>)
},
}
</script>

View File

@ -0,0 +1,31 @@
<script>
import Select, { Option } from '../index'
import '../assets/index.less'
export default {
methods: {
onChange (value, options) {
console.log(`selected ${value}`)
},
},
render () {
return (<div>
<h2>Select optionFilterProp</h2>
<div style={{ width: '300px' }}>
<Select
defaultValue='张三'
style={{ width: '500px' }}
placeholder='placeholder'
optionFilterProp='desc'
onChange={this.onChange}
>
<Option value='张三' desc='张三 zhang san'>ddd</Option>
<Option value='李四' desc='李四 li si'>李四</Option>
<Option value='王五' desc='王五 wang wu'>王五</Option>
</Select>
</div>
</div>)
},
}
</script>

View File

@ -0,0 +1,30 @@
<script>
import Select, { Option } from '../index'
import '../assets/index.less'
export default {
methods: {
onChange (value, options) {
console.log(`selected ${value}`)
},
},
render () {
const cases = {
0: { name: 'Case 1' },
1: { name: 'Case 2' },
2: { name: 'Case 3' },
}
return (<div>
<h2>Select optionLabelProp</h2>
<Select style={{ width: '500px' }} optionLabelProp='children' multiple allowClear>
{
Object.keys(cases).map(key => (
<Option key={key} value={key}>{cases[key].name}</Option>
))
}
</Select>
</div>)
},
}
</script>

View File

@ -1,4 +1,4 @@
import { getPropsData, getSlotOptions, getKey } from '../_util/props-util'
import { getPropsData, getSlotOptions, getKey, getAttrs } from '../_util/props-util'
export function getValuePropValue (child) {
const props = getPropsData(child)
if ('value' in props) {
@ -26,7 +26,12 @@ export function getPropValue (child, prop) {
return child.componentOptions.children
}
}
return getPropsData(child)[prop]
const data = getPropsData(child)
if (prop in data) {
return data[prop]
} else {
return getAttrs(child)[prop]
}
}
export function isMultiple (props) {
@ -150,7 +155,12 @@ export function defaultFilterFn (input, child) {
if (props.disabled) {
return false
}
const value = String(getPropValue(child, this.optionFilterProp))
let value = getPropValue(child, this.optionFilterProp)
if (value.length && value[0].text) {
value = value[0].text
} else {
value = String(value)
}
return (
value.toLowerCase().indexOf(input.toLowerCase()) > -1
)