2018-02-06 17:22:36 +08:00
|
|
|
import PropTypes from '../_util/vue-types'
|
2018-09-05 21:28:54 +08:00
|
|
|
import { Provider, create } from '../_util/store'
|
|
|
|
import { default as SubPopupMenu, getActiveKey } from './SubPopupMenu'
|
2018-02-06 17:22:36 +08:00
|
|
|
import BaseMixin from '../_util/BaseMixin'
|
2018-09-05 21:28:54 +08:00
|
|
|
import hasProp, { getOptionProps } from '../_util/props-util'
|
2018-01-04 19:06:54 +08:00
|
|
|
import commonPropsType from './commonPropsType'
|
2017-12-12 13:49:02 +08:00
|
|
|
|
|
|
|
const Menu = {
|
|
|
|
name: 'Menu',
|
|
|
|
props: {
|
2018-01-04 19:06:54 +08:00
|
|
|
...commonPropsType,
|
2018-01-19 18:18:17 +08:00
|
|
|
selectable: PropTypes.bool.def(true),
|
2017-12-12 13:49:02 +08:00
|
|
|
},
|
2018-09-05 21:28:54 +08:00
|
|
|
mixins: [BaseMixin],
|
2017-12-12 13:49:02 +08:00
|
|
|
|
|
|
|
data () {
|
2018-09-05 21:28:54 +08:00
|
|
|
const props = getOptionProps(this)
|
|
|
|
let selectedKeys = props.defaultSelectedKeys
|
|
|
|
let openKeys = props.defaultOpenKeys
|
|
|
|
if ('selectedKeys' in props) {
|
|
|
|
selectedKeys = props.selectedKeys || []
|
2018-01-08 18:31:04 +08:00
|
|
|
}
|
2018-09-05 21:28:54 +08:00
|
|
|
if ('openKeys' in props) {
|
|
|
|
openKeys = props.openKeys || []
|
2018-01-08 18:31:04 +08:00
|
|
|
}
|
|
|
|
|
2018-09-05 21:28:54 +08:00
|
|
|
this.store = create({
|
|
|
|
selectedKeys,
|
|
|
|
openKeys,
|
|
|
|
activeKey: { '0-menu-': getActiveKey({ ...props, children: this.$slots.default || [] }, props.activeKey) },
|
|
|
|
})
|
|
|
|
|
|
|
|
// this.isRootMenu = true // 声明在props上
|
|
|
|
return {}
|
2017-12-12 13:49:02 +08:00
|
|
|
},
|
2017-12-27 18:15:11 +08:00
|
|
|
watch: {
|
2018-09-05 21:28:54 +08:00
|
|
|
selectedKeys (val) {
|
|
|
|
this.store.setState({
|
|
|
|
selectedKeys: val || [],
|
|
|
|
})
|
|
|
|
},
|
|
|
|
openKeys (val) {
|
|
|
|
this.store.setState({
|
|
|
|
openKeys: val || [],
|
|
|
|
})
|
2017-12-27 18:15:11 +08:00
|
|
|
},
|
2018-09-05 21:28:54 +08:00
|
|
|
// '$props': {
|
|
|
|
// handler: function (nextProps) {
|
|
|
|
// if (hasProp(this, 'selectedKeys')) {
|
|
|
|
// this.setState({
|
|
|
|
// sSelectedKeys: nextProps.selectedKeys || [],
|
|
|
|
// })
|
|
|
|
// }
|
|
|
|
// if (hasProp(this, 'openKeys')) {
|
|
|
|
// this.setState({
|
|
|
|
// sOpenKeys: nextProps.openKeys || [],
|
|
|
|
// })
|
|
|
|
// }
|
|
|
|
// },
|
|
|
|
// deep: true,
|
|
|
|
// },
|
2017-12-12 13:49:02 +08:00
|
|
|
},
|
|
|
|
methods: {
|
2018-01-17 16:12:53 +08:00
|
|
|
// onDestroy (key) {
|
|
|
|
// const state = this.$data
|
|
|
|
// const sSelectedKeys = state.sSelectedKeys
|
|
|
|
// const sOpenKeys = state.sOpenKeys
|
|
|
|
// let index = sSelectedKeys.indexOf(key)
|
|
|
|
// if (!hasProp(this, 'selectedKeys') && index !== -1) {
|
|
|
|
// sSelectedKeys.splice(index, 1)
|
|
|
|
// }
|
|
|
|
// index = sOpenKeys.indexOf(key)
|
|
|
|
// if (!hasProp(this, 'openKeys') && index !== -1) {
|
|
|
|
// sOpenKeys.splice(index, 1)
|
|
|
|
// }
|
|
|
|
// },
|
2017-12-12 13:49:02 +08:00
|
|
|
|
|
|
|
onSelect (selectInfo) {
|
|
|
|
const props = this.$props
|
|
|
|
if (props.selectable) {
|
|
|
|
// root menu
|
2018-09-05 21:28:54 +08:00
|
|
|
let selectedKeys = this.store.getState().selectedKeys
|
2017-12-12 13:49:02 +08:00
|
|
|
const selectedKey = selectInfo.key
|
|
|
|
if (props.multiple) {
|
2018-09-05 21:28:54 +08:00
|
|
|
selectedKeys = selectedKeys.concat([selectedKey])
|
2017-12-12 13:49:02 +08:00
|
|
|
} else {
|
2018-09-05 21:28:54 +08:00
|
|
|
selectedKeys = [selectedKey]
|
2017-12-12 13:49:02 +08:00
|
|
|
}
|
2018-01-02 19:05:02 +08:00
|
|
|
if (!hasProp(this, 'selectedKeys')) {
|
2018-09-05 21:28:54 +08:00
|
|
|
this.store.setState({
|
|
|
|
selectedKeys,
|
2017-12-12 13:49:02 +08:00
|
|
|
})
|
|
|
|
}
|
2018-01-12 16:10:41 +08:00
|
|
|
this.__emit('select', {
|
2017-12-12 13:49:02 +08:00
|
|
|
...selectInfo,
|
2018-09-05 21:28:54 +08:00
|
|
|
selectedKeys: selectedKeys,
|
2017-12-12 13:49:02 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
onClick (e) {
|
2018-01-12 16:10:41 +08:00
|
|
|
this.__emit('click', e)
|
2017-12-12 13:49:02 +08:00
|
|
|
},
|
2018-09-05 21:28:54 +08:00
|
|
|
// onKeyDown needs to be exposed as a instance method
|
|
|
|
// e.g., in rc-select, we need to navigate menu item while
|
|
|
|
// current active item is rc-select input box rather than the menu itself
|
|
|
|
onKeyDown (e, callback) {
|
|
|
|
this.$refs.innerMenu.getWrappedInstance().onKeyDown(e, callback)
|
|
|
|
},
|
2018-01-17 16:12:53 +08:00
|
|
|
onOpenChange (event) {
|
2018-09-05 21:28:54 +08:00
|
|
|
const openKeys = this.store.getState().openKeys.concat()
|
2017-12-12 13:49:02 +08:00
|
|
|
let changed = false
|
|
|
|
const processSingle = (e) => {
|
|
|
|
let oneChanged = false
|
|
|
|
if (e.open) {
|
2018-09-05 21:28:54 +08:00
|
|
|
oneChanged = openKeys.indexOf(e.key) === -1
|
2017-12-12 13:49:02 +08:00
|
|
|
if (oneChanged) {
|
2018-09-05 21:28:54 +08:00
|
|
|
openKeys.push(e.key)
|
2017-12-12 13:49:02 +08:00
|
|
|
}
|
|
|
|
} else {
|
2018-09-05 21:28:54 +08:00
|
|
|
const index = openKeys.indexOf(e.key)
|
2017-12-12 13:49:02 +08:00
|
|
|
oneChanged = index !== -1
|
|
|
|
if (oneChanged) {
|
2018-09-05 21:28:54 +08:00
|
|
|
openKeys.splice(index, 1)
|
2017-12-12 13:49:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
changed = changed || oneChanged
|
|
|
|
}
|
2018-01-17 16:12:53 +08:00
|
|
|
if (Array.isArray(event)) {
|
2017-12-12 13:49:02 +08:00
|
|
|
// batch change call
|
2018-01-17 16:12:53 +08:00
|
|
|
event.forEach(processSingle)
|
2017-12-12 13:49:02 +08:00
|
|
|
} else {
|
2018-01-17 16:12:53 +08:00
|
|
|
processSingle(event)
|
2017-12-12 13:49:02 +08:00
|
|
|
}
|
|
|
|
if (changed) {
|
2018-01-02 19:05:02 +08:00
|
|
|
if (!hasProp(this, 'openKeys')) {
|
2018-09-05 21:28:54 +08:00
|
|
|
this.store.setState({ openKeys })
|
2017-12-12 13:49:02 +08:00
|
|
|
}
|
2018-09-05 21:28:54 +08:00
|
|
|
this.__emit('openChange', openKeys)
|
2017-12-12 13:49:02 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
onDeselect (selectInfo) {
|
|
|
|
const props = this.$props
|
|
|
|
if (props.selectable) {
|
2018-09-05 21:28:54 +08:00
|
|
|
const selectedKeys = this.store.getState().selectedKeys.concat()
|
2017-12-12 13:49:02 +08:00
|
|
|
const selectedKey = selectInfo.key
|
2018-09-05 21:28:54 +08:00
|
|
|
const index = selectedKeys.indexOf(selectedKey)
|
2017-12-12 13:49:02 +08:00
|
|
|
if (index !== -1) {
|
2018-09-05 21:28:54 +08:00
|
|
|
selectedKeys.splice(index, 1)
|
2017-12-12 13:49:02 +08:00
|
|
|
}
|
2018-01-02 19:05:02 +08:00
|
|
|
if (!hasProp(this, 'selectedKeys')) {
|
2018-09-05 21:28:54 +08:00
|
|
|
this.store.setState({
|
|
|
|
selectedKeys,
|
2017-12-12 13:49:02 +08:00
|
|
|
})
|
|
|
|
}
|
2018-01-12 16:10:41 +08:00
|
|
|
this.__emit('deselect', {
|
2017-12-12 13:49:02 +08:00
|
|
|
...selectInfo,
|
2018-09-05 21:28:54 +08:00
|
|
|
selectedKeys: selectedKeys,
|
2017-12-12 13:49:02 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
getOpenTransitionName () {
|
|
|
|
const props = this.$props
|
|
|
|
let transitionName = props.openTransitionName
|
|
|
|
const animationName = props.openAnimation
|
|
|
|
if (!transitionName && typeof animationName === 'string') {
|
|
|
|
transitionName = `${props.prefixCls}-open-${animationName}`
|
|
|
|
}
|
|
|
|
return transitionName
|
|
|
|
},
|
|
|
|
|
2018-09-05 21:28:54 +08:00
|
|
|
// isInlineMode () {
|
|
|
|
// return this.$props.mode === 'inline'
|
|
|
|
// },
|
2017-12-12 13:49:02 +08:00
|
|
|
|
2018-09-05 21:28:54 +08:00
|
|
|
// lastOpenSubMenu () {
|
|
|
|
// let lastOpen = []
|
|
|
|
// const { sOpenKeys } = this.$data
|
|
|
|
// if (sOpenKeys.length) {
|
|
|
|
// lastOpen = this.getFlatInstanceArray().filter((c) => {
|
|
|
|
// return c && sOpenKeys.indexOf(c.eventKey) !== -1
|
|
|
|
// })
|
|
|
|
// }
|
|
|
|
// return lastOpen[0]
|
|
|
|
// },
|
2017-12-12 13:49:02 +08:00
|
|
|
|
2018-09-05 21:28:54 +08:00
|
|
|
// renderMenuItem (c, i, subIndex) {
|
|
|
|
// if (!c) {
|
|
|
|
// return null
|
|
|
|
// }
|
|
|
|
// const state = this.$data
|
|
|
|
// const extraProps = {
|
|
|
|
// openKeys: state.sOpenKeys,
|
|
|
|
// selectedKeys: state.sSelectedKeys,
|
|
|
|
// triggerSubMenuAction: this.$props.triggerSubMenuAction,
|
|
|
|
// isRootMenu: this.isRootMenu,
|
|
|
|
// }
|
|
|
|
// return this.renderCommonMenuItem(c, i, subIndex, extraProps)
|
|
|
|
// },
|
2017-12-12 13:49:02 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
render () {
|
2018-09-05 21:28:54 +08:00
|
|
|
const props = getOptionProps(this)
|
|
|
|
const subPopupMenuProps = {
|
|
|
|
props: {
|
|
|
|
...props,
|
|
|
|
openTransitionName: this.getOpenTransitionName(),
|
|
|
|
parentMenu: this,
|
|
|
|
children: this.$slots.default || [],
|
|
|
|
__propsSymbol__: Symbol(),
|
|
|
|
},
|
|
|
|
class: `${props.prefixCls}-root`,
|
|
|
|
on: {
|
|
|
|
click: this.onClick,
|
|
|
|
openChange: this.onOpenChange,
|
|
|
|
deselect: this.onDeselect,
|
|
|
|
select: this.onSelect,
|
|
|
|
},
|
|
|
|
ref: 'innerMenu',
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
<Provider store={this.store}>
|
|
|
|
<SubPopupMenu {...subPopupMenuProps} />
|
|
|
|
</Provider>
|
|
|
|
)
|
2017-12-12 13:49:02 +08:00
|
|
|
},
|
|
|
|
}
|
|
|
|
export default Menu
|
2018-03-19 10:16:27 +08:00
|
|
|
|