add vc-cascader

pull/9/head
tjz 2018-03-02 22:12:52 +08:00
parent dd1266ee61
commit de23e4de11
7 changed files with 462 additions and 376 deletions

View File

@ -62,13 +62,18 @@ export function cloneElement (n, nodeProps, deep) {
const node = cloneVNode(ele, deep)
const { props = {}, key, on = {}, children } = nodeProps
const data = node.data || {}
const { style = data.style,
class: cls = data.class,
attrs = data.attrs,
const { style = {},
class: cls = {},
attrs = {},
ref,
domProps = data.domProps,
domProps = {},
} = nodeProps
node.data = Object.assign({}, data, { style, attrs, class: cls, domProps })
node.data = Object.assign({}, data, {
style: { ...data.style, ...style },
attrs: { ...data.attrs, ...attrs },
class: { ...data.class, ...cls },
domProps: { ...data.domProps, ...domProps },
})
if (node.componentOptions) {
node.componentOptions.propsData = node.componentOptions.propsData || {}
node.componentOptions.listeners = node.componentOptions.listeners || {}

View File

@ -1,11 +1,13 @@
<script>
import React, { Component, cloneElement } from 'react';
import PropTypes from 'prop-types';
import Trigger from 'rc-trigger';
import Menus from './Menus';
import KeyCode from 'rc-util/lib/KeyCode';
import arrayTreeFilter from 'array-tree-filter';
import shallowEqualArrays from 'shallow-equal/arrays';
import PropTypes from '../_util/vue-types'
import Trigger from '../trigger'
import Menus from './Menus'
import KeyCode from '../_util/KeyCode'
import arrayTreeFilter from 'array-tree-filter'
import shallowEqualArrays from 'shallow-equal/arrays'
import { hasProp, getEvents } from '../_util/props-util'
import BaseMixin from '../_util/BaseMixin'
import { cloneElement } from '../_util/vnode'
const BUILT_IN_PLACEMENTS = {
bottomLeft: {
@ -40,274 +42,278 @@ const BUILT_IN_PLACEMENTS = {
adjustY: 1,
},
},
};
}
class Cascader extends Component {
constructor(props) {
super(props);
let initialValue = [];
if ('value' in props) {
initialValue = props.value || [];
} else if ('defaultValue' in props) {
initialValue = props.defaultValue || [];
export default {
props: {
value: PropTypes.array,
defaultValue: PropTypes.array,
options: PropTypes.array.def([]).isRequired,
// onChange: PropTypes.func,
// onPopupVisibleChange: PropTypes.func,
popupVisible: PropTypes.bool,
disabled: PropTypes.bool.def(false),
transitionName: PropTypes.string.def(''),
popupClassName: PropTypes.string.def(''),
popupStyle: PropTypes.object.def({}),
popupPlacement: PropTypes.string.def('bottomLeft'),
prefixCls: PropTypes.string.def('rc-cascader'),
dropdownMenuColumnStyle: PropTypes.object,
builtinPlacements: PropTypes.object.def(BUILT_IN_PLACEMENTS),
loadData: PropTypes.func,
changeOnSelect: PropTypes.bool,
// onKeyDown: PropTypes.func,
expandTrigger: PropTypes.string.def('click'),
},
mixins: [BaseMixin],
data () {
let initialValue = []
const { value, defaultValue, popupVisible } = this
if (hasProp(this, 'value')) {
initialValue = value || []
} else if (hasProp(this, 'defaultValue')) {
initialValue = defaultValue || []
}
this.state = {
popupVisible: props.popupVisible,
activeValue: initialValue,
value: initialValue,
};
}
componentWillReceiveProps(nextProps) {
if ('value' in nextProps && !shallowEqualArrays(this.props.value, nextProps.value)) {
const newValues = {
value: nextProps.value || [],
activeValue: nextProps.value || [],
};
// allow activeValue diff from value
// https://github.com/ant-design/ant-design/issues/2767
if ('loadData' in nextProps) {
delete newValues.activeValue;
return {
sPopupVisible: popupVisible,
sActiveValue: initialValue,
sValue: initialValue,
}
},
watch: {
value (val, oldValue) {
if (!shallowEqualArrays(val, oldValue)) {
const newValues = {
value: oldValue || [],
activeValue: oldValue || [],
}
// allow activeValue diff from value
// https://github.com/ant-design/ant-design/issues/2767
if (hasProp(this, 'loadData')) {
delete newValues.activeValue
}
this.setState(newValues)
}
this.setState(newValues);
}
if ('popupVisible' in nextProps) {
},
popupVisible (val) {
this.setState({
popupVisible: nextProps.popupVisible,
});
}
}
getPopupDOMNode() {
return this.trigger.getPopupDomNode();
}
getCurrentLevelOptions() {
const { options } = this.props;
const { activeValue = [] } = this.state;
const result = arrayTreeFilter(options, (o, level) => o.value === activeValue[level]);
if (result[result.length - 2]) {
return result[result.length - 2].children;
}
return [...options].filter(o => !o.disabled);
}
getActiveOptions(activeValue) {
return arrayTreeFilter(this.props.options, (o, level) => o.value === activeValue[level]);
}
setPopupVisible = (popupVisible) => {
if (!('popupVisible' in this.props)) {
this.setState({ popupVisible });
}
// sync activeValue with value when panel open
if (popupVisible && !this.state.visible) {
this.setState({
activeValue: this.state.value,
});
}
this.props.onPopupVisibleChange(popupVisible);
}
handleChange = (options, setProps, e) => {
if (e.type !== 'keydown' || e.keyCode === KeyCode.ENTER) {
this.props.onChange(options.map(o => o.value), options);
this.setPopupVisible(setProps.visible);
}
}
handlePopupVisibleChange = (popupVisible) => {
this.setPopupVisible(popupVisible);
}
handleMenuSelect = (targetOption, menuIndex, e) => {
sPopupVisible: val,
})
},
},
methods: {
getPopupDOMNode () {
return this.$refs.trigger.getPopupDomNode()
},
getCurrentLevelOptions () {
const { options, sActiveValue = [] } = this
const result = arrayTreeFilter(options, (o, level) => o.value === sActiveValue[level])
if (result[result.length - 2]) {
return result[result.length - 2].children
}
return [...options].filter(o => !o.disabled)
},
getActiveOptions (activeValue) {
return arrayTreeFilter(this.options, (o, level) => o.value === activeValue[level])
},
setPopupVisible (popupVisible) {
if (!hasProp(this, 'popupVisible')) {
this.setState({ sPopupVisible: popupVisible })
}
// sync activeValue with value when panel open
if (popupVisible && !this.sVisible) {
this.setState({
sActiveValue: this.sValue,
})
}
this.__emit('popupVisibleChange', popupVisible)
},
handleChange (options, setProps, e) {
if (e.type !== 'keydown' || e.keyCode === KeyCode.ENTER) {
this.__emit('change', options.map(o => o.value), options)
this.setPopupVisible(setProps.visible)
}
},
handlePopupVisibleChange (popupVisible) {
this.setPopupVisible(popupVisible)
},
handleMenuSelect (targetOption, menuIndex, e) {
// Keep focused state for keyboard support
const triggerNode = this.trigger.getRootDomNode();
if (triggerNode && triggerNode.focus) {
triggerNode.focus();
}
const { changeOnSelect, loadData, expandTrigger } = this.props;
if (!targetOption || targetOption.disabled) {
return;
}
let { activeValue } = this.state;
activeValue = activeValue.slice(0, menuIndex + 1);
activeValue[menuIndex] = targetOption.value;
const activeOptions = this.getActiveOptions(activeValue);
if (targetOption.isLeaf === false && !targetOption.children && loadData) {
if (changeOnSelect) {
this.handleChange(activeOptions, { visible: true }, e);
const triggerNode = this.$refs.trigger.getRootDomNode()
if (triggerNode && triggerNode.focus) {
triggerNode.focus()
}
this.setState({ activeValue });
loadData(activeOptions);
return;
}
const newState = {};
if (!targetOption.children || !targetOption.children.length) {
this.handleChange(activeOptions, { visible: false }, e);
// set value to activeValue when select leaf option
newState.value = activeValue;
const { changeOnSelect, loadData, expandTrigger } = this
if (!targetOption || targetOption.disabled) {
return
}
let { sActiveValue } = this
sActiveValue = sActiveValue.slice(0, menuIndex + 1)
sActiveValue[menuIndex] = targetOption.value
const activeOptions = this.getActiveOptions(sActiveValue)
if (targetOption.isLeaf === false && !targetOption.children && loadData) {
if (changeOnSelect) {
this.handleChange(activeOptions, { visible: true }, e)
}
this.setState({ sActiveValue })
loadData(activeOptions)
return
}
const newState = {}
if (!targetOption.children || !targetOption.children.length) {
this.handleChange(activeOptions, { visible: false }, e)
// set value to activeValue when select leaf option
newState.sValue = sActiveValue
// add e.type judgement to prevent `onChange` being triggered by mouseEnter
} else if (changeOnSelect && (e.type === 'click' || e.type === 'keydown')) {
if (expandTrigger === 'hover') {
this.handleChange(activeOptions, { visible: false }, e);
} else {
this.handleChange(activeOptions, { visible: true }, e);
} else if (changeOnSelect && (e.type === 'click' || e.type === 'keydown')) {
if (expandTrigger === 'hover') {
this.handleChange(activeOptions, { visible: false }, e)
} else {
this.handleChange(activeOptions, { visible: true }, e)
}
// set value to activeValue on every select
newState.sValue = sActiveValue
}
// set value to activeValue on every select
newState.value = activeValue;
}
newState.activeValue = activeValue;
// not change the value by keyboard
if ('value' in this.props ||
newState.sActiveValue = sActiveValue
// not change the value by keyboard
if (hasProp(this, 'value') ||
(e.type === 'keydown' && e.keyCode !== KeyCode.ENTER)) {
delete newState.value;
}
this.setState(newState);
}
handleKeyDown = (e) => {
const { children } = this.props;
// https://github.com/ant-design/ant-design/issues/6717
// Don't bind keyboard support when children specify the onKeyDown
if (children && children.props.onKeyDown) {
children.props.onKeyDown(e);
return;
}
const activeValue = [...this.state.activeValue];
const currentLevel = activeValue.length - 1 < 0 ? 0 : activeValue.length - 1;
const currentOptions = this.getCurrentLevelOptions();
const currentIndex = currentOptions.map(o => o.value).indexOf(activeValue[currentLevel]);
if (e.keyCode !== KeyCode.DOWN &&
delete newState.sValue
}
this.setState(newState)
},
handleKeyDown (e) {
const { $slots } = this
const children = $slots.default && $slots.default[0]
// https://github.com/ant-design/ant-design/issues/6717
// Don't bind keyboard support when children specify the onKeyDown
if (children) {
const keydown = getEvents(children).keydown
if (keydown) {
keydown(e)
return
}
}
const activeValue = [...this.sActiveValue]
const currentLevel = activeValue.length - 1 < 0 ? 0 : activeValue.length - 1
const currentOptions = this.getCurrentLevelOptions()
const currentIndex = currentOptions.map(o => o.value).indexOf(activeValue[currentLevel])
if (e.keyCode !== KeyCode.DOWN &&
e.keyCode !== KeyCode.UP &&
e.keyCode !== KeyCode.LEFT &&
e.keyCode !== KeyCode.RIGHT &&
e.keyCode !== KeyCode.ENTER &&
e.keyCode !== KeyCode.BACKSPACE &&
e.keyCode !== KeyCode.ESC) {
return;
}
// Press any keys above to reopen menu
if (!this.state.popupVisible &&
return
}
// Press any keys above to reopen menu
if (!this.sPopupVisible &&
e.keyCode !== KeyCode.BACKSPACE &&
e.keyCode !== KeyCode.LEFT &&
e.keyCode !== KeyCode.RIGHT &&
e.keyCode !== KeyCode.ESC) {
this.setPopupVisible(true);
return;
}
if (e.keyCode === KeyCode.DOWN || e.keyCode === KeyCode.UP) {
let nextIndex = currentIndex;
if (nextIndex !== -1) {
if (e.keyCode === KeyCode.DOWN) {
nextIndex += 1;
nextIndex = nextIndex >= currentOptions.length ? 0 : nextIndex;
this.setPopupVisible(true)
return
}
if (e.keyCode === KeyCode.DOWN || e.keyCode === KeyCode.UP) {
let nextIndex = currentIndex
if (nextIndex !== -1) {
if (e.keyCode === KeyCode.DOWN) {
nextIndex += 1
nextIndex = nextIndex >= currentOptions.length ? 0 : nextIndex
} else {
nextIndex -= 1
nextIndex = nextIndex < 0 ? currentOptions.length - 1 : nextIndex
}
} else {
nextIndex -= 1;
nextIndex = nextIndex < 0 ? currentOptions.length - 1 : nextIndex;
nextIndex = 0
}
} else {
nextIndex = 0;
activeValue[currentLevel] = currentOptions[nextIndex].value
} else if (e.keyCode === KeyCode.LEFT || e.keyCode === KeyCode.BACKSPACE) {
activeValue.splice(activeValue.length - 1, 1)
} else if (e.keyCode === KeyCode.RIGHT) {
if (currentOptions[currentIndex] && currentOptions[currentIndex].children) {
activeValue.push(currentOptions[currentIndex].children[0].value)
}
} else if (e.keyCode === KeyCode.ESC) {
this.setPopupVisible(false)
return
}
activeValue[currentLevel] = currentOptions[nextIndex].value;
} else if (e.keyCode === KeyCode.LEFT || e.keyCode === KeyCode.BACKSPACE) {
activeValue.splice(activeValue.length - 1, 1);
} else if (e.keyCode === KeyCode.RIGHT) {
if (currentOptions[currentIndex] && currentOptions[currentIndex].children) {
activeValue.push(currentOptions[currentIndex].children[0].value);
if (!activeValue || activeValue.length === 0) {
this.setPopupVisible(false)
}
} else if (e.keyCode === KeyCode.ESC) {
this.setPopupVisible(false);
return;
}
if (!activeValue || activeValue.length === 0) {
this.setPopupVisible(false);
}
const activeOptions = this.getActiveOptions(activeValue);
const targetOption = activeOptions[activeOptions.length - 1];
this.handleMenuSelect(targetOption, activeOptions.length - 1, e);
const activeOptions = this.getActiveOptions(activeValue)
const targetOption = activeOptions[activeOptions.length - 1]
this.handleMenuSelect(targetOption, activeOptions.length - 1, e)
this.__emit('keydown', e)
},
},
if (this.props.onKeyDown) {
this.props.onKeyDown(e);
}
}
saveTrigger = (node) => {
this.trigger = node;
}
render() {
render () {
const {
$props, $slots, sValue, sActiveValue, handleMenuSelect,
sPopupVisible, handlePopupVisibleChange, handleKeyDown,
} = this
const {
prefixCls, transitionName, popupClassName, options, disabled,
builtinPlacements, popupPlacement, children, ...restProps,
} = this.props;
builtinPlacements, popupPlacement, ...restProps } = $props
// Did not show popup when there is no options
let menus = <div />;
let emptyMenuClassName = '';
let menus = <div />
let emptyMenuClassName = ''
if (options && options.length > 0) {
const menusProps = {
props: {
...$props,
value: sValue,
activeValue: sActiveValue,
visible: sPopupVisible,
},
on: {
select: handleMenuSelect,
},
}
menus = (
<Menus
{...this.props}
value={this.state.value}
activeValue={this.state.activeValue}
onSelect={this.handleMenuSelect}
visible={this.state.popupVisible}
{...menusProps}
/>
);
)
} else {
emptyMenuClassName = ` ${prefixCls}-menus-empty`;
emptyMenuClassName = ` ${prefixCls}-menus-empty`
}
const triggerProps = {
props: {
...restProps,
disabled: disabled,
popupPlacement: popupPlacement,
builtinPlacements: builtinPlacements,
popupTransitionName: transitionName,
action: disabled ? [] : ['click'],
popupVisible: disabled ? false : sPopupVisible,
prefixCls: `${prefixCls}-menus`,
popupClassName: popupClassName + emptyMenuClassName,
},
on: {
popupVisibleChange: handlePopupVisibleChange,
},
ref: 'trigger',
}
return (
<Trigger
ref={this.saveTrigger}
{...restProps}
options={options}
disabled={disabled}
popupPlacement={popupPlacement}
builtinPlacements={builtinPlacements}
popupTransitionName={transitionName}
action={disabled ? [] : ['click']}
popupVisible={disabled ? false : this.state.popupVisible}
onPopupVisibleChange={this.handlePopupVisibleChange}
prefixCls={`${prefixCls}-menus`}
popupClassName={popupClassName + emptyMenuClassName}
popup={menus}
>
{cloneElement(children, {
onKeyDown: this.handleKeyDown,
tabIndex: disabled ? undefined : 0,
<Trigger {...triggerProps}>
{$slots.default && cloneElement($slots.default[0], {
on: {
keydown: handleKeyDown,
},
attrs: {
tabIndex: disabled ? undefined : 0,
},
})}
<template slot='popup'>
{menus}
</template>
</Trigger>
);
}
)
},
}
Cascader.defaultProps = {
options: [],
onChange() {},
onPopupVisibleChange() {},
disabled: false,
transitionName: '',
prefixCls: 'rc-cascader',
popupClassName: '',
popupPlacement: 'bottomLeft',
builtinPlacements: BUILT_IN_PLACEMENTS,
expandTrigger: 'click',
};
Cascader.propTypes = {
value: PropTypes.array,
defaultValue: PropTypes.array,
options: PropTypes.array.isRequired,
onChange: PropTypes.func,
onPopupVisibleChange: PropTypes.func,
popupVisible: PropTypes.bool,
disabled: PropTypes.bool,
transitionName: PropTypes.string,
popupClassName: PropTypes.string,
popupPlacement: PropTypes.string,
prefixCls: PropTypes.string,
dropdownMenuColumnStyle: PropTypes.object,
builtinPlacements: PropTypes.object,
loadData: PropTypes.func,
changeOnSelect: PropTypes.bool,
children: PropTypes.node,
onKeyDown: PropTypes.func,
expandTrigger: PropTypes.string,
};
export default Cascader;
</script>

View File

@ -1,156 +1,150 @@
<script>
import React from 'react'
import PropTypes from 'prop-types'
import PropTypes from '../_util/vue-types'
import arrayTreeFilter from 'array-tree-filter'
import { findDOMNode } from 'react-dom'
class Menus extends React.Component {
constructor (props) {
super(props)
import BaseMixin from '../_util/BaseMixin'
export default {
mixins: [BaseMixin],
props: {
value: PropTypes.array.def([]),
activeValue: PropTypes.array.def([]),
options: PropTypes.array.isRequired,
prefixCls: PropTypes.string.def('rc-cascader-menus'),
expandTrigger: PropTypes.string.def('click'),
// onSelect: PropTypes.func,
visible: PropTypes.bool.def(false),
dropdownMenuColumnStyle: PropTypes.object,
},
data () {
this.menuItems = {}
}
componentDidMount () {
this.scrollActiveItemToView()
}
componentDidUpdate (prevProps) {
if (!prevProps.visible && this.props.visible) {
return {}
},
mounted () {
this.$nextTick(() => {
this.scrollActiveItemToView()
}
}
getOption (option, menuIndex) {
const { prefixCls, expandTrigger } = this.props
const onSelect = this.props.onSelect.bind(this, option, menuIndex)
let expandProps = {
onClick: onSelect,
}
let menuItemCls = `${prefixCls}-menu-item`
const hasChildren = option.children && option.children.length > 0
if (hasChildren || option.isLeaf === false) {
menuItemCls += ` ${prefixCls}-menu-item-expand`
}
if (expandTrigger === 'hover' && hasChildren) {
expandProps = {
onMouseEnter: this.delayOnSelect.bind(this, onSelect),
onMouseLeave: this.delayOnSelect.bind(this),
onClick: onSelect,
})
},
watch: {
visible (val) {
if (val) {
this.$nextTick(() => {
this.scrollActiveItemToView()
})
}
}
if (this.isActiveOption(option, menuIndex)) {
menuItemCls += ` ${prefixCls}-menu-item-active`
expandProps.ref = this.saveMenuItem(menuIndex)
}
if (option.disabled) {
menuItemCls += ` ${prefixCls}-menu-item-disabled`
}
if (option.loading) {
menuItemCls += ` ${prefixCls}-menu-item-loading`
}
let title = ''
if (option.title) {
title = option.title
} else if (typeof option.label === 'string') {
title = option.label
}
return (
<li
key={option.value}
className={menuItemCls}
title={title}
{...expandProps}
>
{option.label}
</li>
)
}
},
},
methods: {
getOption (option, menuIndex) {
const { prefixCls, expandTrigger } = this
const onSelect = (e) => {
this.__emit('select', option, menuIndex, e)
}
const expandProps = {
attrs: {
},
on: {
click: onSelect,
},
key: option.value,
}
let menuItemCls = `${prefixCls}-menu-item`
const hasChildren = option.children && option.children.length > 0
if (hasChildren || option.isLeaf === false) {
menuItemCls += ` ${prefixCls}-menu-item-expand`
}
if (expandTrigger === 'hover' && hasChildren) {
expandProps.on = {
mouseenter: this.delayOnSelect.bind(this, onSelect),
mouseleave: this.delayOnSelect.bind(this),
click: onSelect,
}
}
if (this.isActiveOption(option, menuIndex)) {
menuItemCls += ` ${prefixCls}-menu-item-active`
expandProps.ref = this.getMenuItemRef(menuIndex)
}
if (option.disabled) {
menuItemCls += ` ${prefixCls}-menu-item-disabled`
}
if (option.loading) {
menuItemCls += ` ${prefixCls}-menu-item-loading`
}
let title = ''
if (option.title) {
title = option.title
} else if (typeof option.label === 'string') {
title = option.label
}
expandProps.attrs.title = title
expandProps.class = menuItemCls
return (
<li {...expandProps}>
{option.label}
</li>
)
},
getActiveOptions (values) {
const activeValue = values || this.props.activeValue
const options = this.props.options
return arrayTreeFilter(options, (o, level) => o.value === activeValue[level])
}
getActiveOptions (values) {
const activeValue = values || this.activeValue
const options = this.options
return arrayTreeFilter(options, (o, level) => o.value === activeValue[level])
},
getShowOptions () {
const { options } = this.props
const result = this.getActiveOptions()
.map(activeOption => activeOption.children)
.filter(activeOption => !!activeOption)
result.unshift(options)
return result
}
getShowOptions () {
const { options } = this
const result = this.getActiveOptions()
.map(activeOption => activeOption.children)
.filter(activeOption => !!activeOption)
result.unshift(options)
return result
},
delayOnSelect (onSelect, ...args) {
if (this.delayTimer) {
clearTimeout(this.delayTimer)
this.delayTimer = null
}
if (typeof onSelect === 'function') {
this.delayTimer = setTimeout(() => {
onSelect(args)
delayOnSelect (onSelect, ...args) {
if (this.delayTimer) {
clearTimeout(this.delayTimer)
this.delayTimer = null
}, 150)
}
}
scrollActiveItemToView () {
// scroll into view
const optionsLength = this.getShowOptions().length
for (let i = 0; i < optionsLength; i++) {
const itemComponent = this.menuItems[i]
if (itemComponent) {
const target = findDOMNode(itemComponent)
target.parentNode.scrollTop = target.offsetTop
}
}
}
if (typeof onSelect === 'function') {
this.delayTimer = setTimeout(() => {
onSelect(args)
this.delayTimer = null
}, 150)
}
},
isActiveOption (option, menuIndex) {
const { activeValue = [] } = this.props
return activeValue[menuIndex] === option.value
}
scrollActiveItemToView () {
// scroll into view
const optionsLength = this.getShowOptions().length
for (let i = 0; i < optionsLength; i++) {
const itemComponent = this.$refs[`menuItems_${i}`]
if (itemComponent) {
const target = itemComponent
target.parentNode.scrollTop = target.offsetTop
}
}
},
saveMenuItem = (index) => (node) => {
this.menuItems[index] = node
}
isActiveOption (option, menuIndex) {
const { activeValue = [] } = this
return activeValue[menuIndex] === option.value
},
getMenuItemRef (index) {
return `menuItems_${index}`
},
},
render () {
const { prefixCls, dropdownMenuColumnStyle } = this.props
const { prefixCls, dropdownMenuColumnStyle } = this
return (
<div>
{this.getShowOptions().map((options, menuIndex) =>
<ul className={`${prefixCls}-menu`} key={menuIndex} style={dropdownMenuColumnStyle}>
<ul class={`${prefixCls}-menu`} key={menuIndex} style={dropdownMenuColumnStyle}>
{options.map(option => this.getOption(option, menuIndex))}
</ul>
)}
</div>
)
}
},
}
Menus.defaultProps = {
options: [],
value: [],
activeValue: [],
onSelect () {},
prefixCls: 'rc-cascader-menus',
visible: false,
expandTrigger: 'click',
}
Menus.propTypes = {
value: PropTypes.array,
activeValue: PropTypes.array,
options: PropTypes.array.isRequired,
prefixCls: PropTypes.string,
expandTrigger: PropTypes.string,
onSelect: PropTypes.func,
visible: PropTypes.bool,
dropdownMenuColumnStyle: PropTypes.object,
}
export default Menus
</script>

View File

@ -0,0 +1,64 @@
<script>
/* eslint-disable no-console */
import '../assets/index.less'
import Cascader from '../index'
const addressOptions = [{
label: '福建',
value: 'fj',
children: [{
label: '福州',
value: 'fuzhou',
children: [{
label: '马尾',
value: 'mawei',
}],
}, {
label: '泉州',
value: 'quanzhou',
}],
}, {
label: '浙江',
value: 'zj',
children: [{
label: '杭州',
value: 'hangzhou',
children: [{
label: '余杭',
value: 'yuhang',
}],
}],
}, {
label: '北京',
value: 'bj',
children: [{
label: '朝阳区',
value: 'chaoyang',
}, {
label: '海淀区',
value: 'haidian',
}],
}]
export default {
data () {
return {
inputValue: '',
}
},
methods: {
onChange (value, selectedOptions) {
console.log(value, selectedOptions)
this.inputValue = selectedOptions.map(o => o.label).join(', ')
},
},
render () {
return (
<Cascader options={addressOptions} onChange={this.onChange} transitionName='slide-up'>
<input value={this.inputValue}/>
</Cascader>
)
},
}
</script>

View File

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

15
package-lock.json generated
View File

@ -416,6 +416,11 @@
"integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=",
"dev": true
},
"array-tree-filter": {
"version": "2.1.0",
"resolved": "http://registry.npm.taobao.org/array-tree-filter/download/array-tree-filter-2.1.0.tgz",
"integrity": "sha1-hzrAD+yDdJ8lWsjdCDgUtPYykZA="
},
"array-union": {
"version": "1.0.2",
"resolved": "http://10.134.27.134:7001/array-union/download/array-union-1.0.2.tgz",
@ -10935,6 +10940,16 @@
"safe-buffer": "5.1.1"
}
},
"shallow-equal": {
"version": "1.0.0",
"resolved": "http://registry.npm.taobao.org/shallow-equal/download/shallow-equal-1.0.0.tgz",
"integrity": "sha1-UI0YOLPeWQq4dXsBGyXkMJAJRfc="
},
"shallowequal": {
"version": "1.0.2",
"resolved": "http://registry.npm.taobao.org/shallowequal/download/shallowequal-1.0.2.tgz",
"integrity": "sha1-FWHb3vuMAUCBADGQhXZNo/z4P48="
},
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npm.taobao.org/shebang-command/download/shebang-command-1.2.0.tgz",

View File

@ -88,6 +88,7 @@
},
"dependencies": {
"add-dom-event-listener": "^1.0.2",
"array-tree-filter": "^2.1.0",
"classnames": "^2.2.5",
"component-classes": "^1.2.6",
"css-animation": "^1.4.1",
@ -100,6 +101,7 @@
"lodash.isplainobject": "^4.0.6",
"moment": "^2.20.1",
"omit.js": "^1.0.0",
"shallow-equal": "^1.0.0",
"shallowequal": "^1.0.2",
"vue": "^2.5.13",
"vue-clipboard2": "0.0.8",