add menu demo
parent
3af108ffcb
commit
f9a85a6c41
|
@ -48,7 +48,7 @@ export function cloneElement (n, nodeProps, clone) {
|
||||||
attrs = data.attrs,
|
attrs = data.attrs,
|
||||||
ref,
|
ref,
|
||||||
} = nodeProps
|
} = nodeProps
|
||||||
node.data = Object.assign(data, { style, attrs, class: cls })
|
node.data = Object.assign({}, data, { style, attrs, class: cls })
|
||||||
if (node.componentOptions) {
|
if (node.componentOptions) {
|
||||||
node.componentOptions.propsData = node.componentOptions.propsData || {}
|
node.componentOptions.propsData = node.componentOptions.propsData || {}
|
||||||
node.componentOptions.listeners = node.componentOptions.listeners || {}
|
node.componentOptions.listeners = node.componentOptions.listeners || {}
|
||||||
|
@ -96,5 +96,5 @@ export function getEvents (child) {
|
||||||
} else if (child.data && child.data.on) {
|
} else if (child.data && child.data.on) {
|
||||||
events = child.data.on
|
events = child.data.on
|
||||||
}
|
}
|
||||||
return events
|
return { ...events }
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { getComponentFromProp } from '../_util/props-util'
|
||||||
export default {
|
export default {
|
||||||
props: itemProps,
|
props: itemProps,
|
||||||
inject: {
|
inject: {
|
||||||
inlineCollapsed: { default: false },
|
getInlineCollapsed: { default: () => { false } },
|
||||||
},
|
},
|
||||||
isMenuItem: 1,
|
isMenuItem: 1,
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -16,20 +16,27 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
render (h) {
|
render (h) {
|
||||||
const { inlineCollapsed, $props: props, $slots, $attrs: attrs, $listeners } = this
|
const { getInlineCollapsed, $props: props, $slots, $attrs: attrs, $listeners } = this
|
||||||
|
const inlineCollapsed = getInlineCollapsed()
|
||||||
const itemProps = {
|
const itemProps = {
|
||||||
props,
|
props,
|
||||||
attrs,
|
attrs,
|
||||||
on: $listeners,
|
on: { ...$listeners },
|
||||||
class: getClass(this),
|
class: getClass(this),
|
||||||
style: getStyle(this),
|
style: getStyle(this),
|
||||||
}
|
}
|
||||||
|
const toolTipProps = {
|
||||||
|
props: {
|
||||||
|
placement: 'right',
|
||||||
|
overlayClassName: `${props.rootPrefixCls}-inline-collapsed-tooltip`,
|
||||||
|
},
|
||||||
|
on: {},
|
||||||
|
}
|
||||||
return <Tooltip
|
return <Tooltip
|
||||||
placement='right'
|
{...toolTipProps}
|
||||||
overlayClassName={`${props.rootPrefixCls}-inline-collapsed-tooltip`}
|
|
||||||
>
|
>
|
||||||
<template slot='title'>
|
<template slot='title'>
|
||||||
{inlineCollapsed && props.level === 1 ? $slots.default : ''}
|
{inlineCollapsed && props.level === 1 ? <span>$slots</span> : ''}
|
||||||
</template>
|
</template>
|
||||||
<Item {...itemProps} ref='menuItem'>
|
<Item {...itemProps} ref='menuItem'>
|
||||||
{$slots.default}
|
{$slots.default}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<md>
|
||||||
|
## 顶部导航
|
||||||
|
水平的顶部导航菜单。
|
||||||
|
</md>
|
||||||
<Menu
|
<Menu
|
||||||
@click="handleClick"
|
v-model="current"
|
||||||
:selectedKeys="[current]"
|
|
||||||
mode="horizontal"
|
mode="horizontal"
|
||||||
>
|
>
|
||||||
<MenuItem key="mail">
|
<MenuItem key="mail">
|
||||||
|
@ -38,15 +41,9 @@ const MenuItem = Menu.Item
|
||||||
export default {
|
export default {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
current: 'mail',
|
current: ['mail'],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
handleClick (e) {
|
|
||||||
console.log(e)
|
|
||||||
this.current = e.key
|
|
||||||
},
|
|
||||||
},
|
|
||||||
components: {
|
components: {
|
||||||
Menu,
|
Menu,
|
||||||
Icon,
|
Icon,
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<md>
|
||||||
|
## 缩起内嵌菜单
|
||||||
|
内嵌菜单可以被缩起/展开。
|
||||||
|
你可以在 [Layout](/components/layout/#components-layout-demo-side) 里查看侧边布局结合的完整示例。
|
||||||
|
</md>
|
||||||
|
<div style="width: 256px">
|
||||||
|
<AntButton type="primary" @click="toggleCollapsed" style="margin-bottom: 16px">
|
||||||
|
<Icon :type="collapsed ? 'menu-unfold' : 'menu-fold'" />
|
||||||
|
</AntButton>
|
||||||
|
<Menu
|
||||||
|
:defaultSelectedKeys="['1']"
|
||||||
|
:defaultOpenKeys="['sub1']"
|
||||||
|
mode="inline"
|
||||||
|
theme="dark"
|
||||||
|
:inlineCollapsed="collapsed"
|
||||||
|
>
|
||||||
|
<MenuItem key="1">
|
||||||
|
<Icon type="pie-chart" />
|
||||||
|
<span>Option 1</span>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem key="2">
|
||||||
|
<Icon type="desktop" />
|
||||||
|
<span>Option 2</span>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem key="3">
|
||||||
|
<Icon type="inbox" />
|
||||||
|
<span>Option 3</span>
|
||||||
|
</MenuItem>
|
||||||
|
<SubMenu key="sub1">
|
||||||
|
<template slot="title">
|
||||||
|
<span><Icon type="mail" /><span>Navigation One</span></span>
|
||||||
|
</template>
|
||||||
|
<MenuItem key="5">Option 5</MenuItem>
|
||||||
|
<MenuItem key="6">Option 6</MenuItem>
|
||||||
|
<MenuItem key="7">Option 7</MenuItem>
|
||||||
|
<MenuItem key="8">Option 8</MenuItem>
|
||||||
|
</SubMenu>
|
||||||
|
<SubMenu key="sub2">
|
||||||
|
<template slot="title">
|
||||||
|
<span><Icon type="appstore" /><span>Navigation Two</span></span>
|
||||||
|
</template>
|
||||||
|
<MenuItem key="9">Option 9</MenuItem>
|
||||||
|
<MenuItem key="10">Option 10</MenuItem>
|
||||||
|
<SubMenu key="sub3" title="Submenu">
|
||||||
|
<MenuItem key="11">Option 11</MenuItem>
|
||||||
|
<MenuItem key="12">Option 12</MenuItem>
|
||||||
|
</SubMenu>
|
||||||
|
</SubMenu>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { Menu, Icon, Button } from 'antd'
|
||||||
|
const SubMenu = Menu.SubMenu
|
||||||
|
const MenuItemGroup = Menu.ItemGroup
|
||||||
|
const MenuItem = Menu.Item
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
collapsed: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleCollapsed () {
|
||||||
|
this.collapsed = !this.collapsed
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Menu,
|
||||||
|
Icon,
|
||||||
|
SubMenu,
|
||||||
|
MenuItemGroup,
|
||||||
|
MenuItem,
|
||||||
|
AntButton: Button,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
|
@ -13,16 +13,12 @@ export const MenuMode = PropTypes.oneOf(['vertical', 'vertical-left', 'vertical-
|
||||||
|
|
||||||
export const menuProps = {
|
export const menuProps = {
|
||||||
theme: PropTypes.oneOf(['light', 'dark']).def('light'),
|
theme: PropTypes.oneOf(['light', 'dark']).def('light'),
|
||||||
mode: MenuMode,
|
mode: MenuMode.def('vertical'),
|
||||||
selectable: PropTypes.bool,
|
selectable: PropTypes.bool,
|
||||||
selectedKeys: PropTypes.arrayOf(PropTypes.string),
|
selectedKeys: PropTypes.arrayOf(PropTypes.string),
|
||||||
defaultSelectedKeys: PropTypes.array,
|
defaultSelectedKeys: PropTypes.array,
|
||||||
openKeys: PropTypes.array,
|
openKeys: PropTypes.array,
|
||||||
defaultOpenKeys: PropTypes.array,
|
defaultOpenKeys: PropTypes.array,
|
||||||
// onOpenChange: (openKeys: string[]) => void;
|
|
||||||
// onSelect: (param: SelectParam) => void;
|
|
||||||
// onDeselect: (param: SelectParam) => void;
|
|
||||||
// onClick: (param: ClickParam) => void;
|
|
||||||
openAnimation: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
openAnimation: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||||
openTransitionName: PropTypes.string,
|
openTransitionName: PropTypes.string,
|
||||||
prefixCls: PropTypes.string.def('ant-menu'),
|
prefixCls: PropTypes.string.def('ant-menu'),
|
||||||
|
@ -40,6 +36,7 @@ export default {
|
||||||
provide () {
|
provide () {
|
||||||
return {
|
return {
|
||||||
inlineCollapsed: this.getInlineCollapsed(),
|
inlineCollapsed: this.getInlineCollapsed(),
|
||||||
|
getInlineCollapsed: this.getInlineCollapsed,
|
||||||
antdMenuTheme: this.$props.theme,
|
antdMenuTheme: this.$props.theme,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -47,38 +44,54 @@ export default {
|
||||||
inject: {
|
inject: {
|
||||||
layoutContext: { default: {}},
|
layoutContext: { default: {}},
|
||||||
},
|
},
|
||||||
|
model: {
|
||||||
|
prop: 'selectedKeys',
|
||||||
|
event: 'selectChange',
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$props': {
|
'$props': {
|
||||||
handler: function (nextProps) {
|
handler: function (nextProps) {
|
||||||
|
const { preProps, sOpenKeys } = this
|
||||||
},
|
|
||||||
deep: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
beforeUpdate () {
|
|
||||||
const { preProps, $props: nextProps, layoutContext, preLayoutContext = {}} = this
|
|
||||||
const { prefixCls } = preProps
|
const { prefixCls } = preProps
|
||||||
if (preProps.mode === 'inline' &&
|
if (preProps.mode === 'inline' && nextProps.mode !== 'inline') {
|
||||||
nextProps.mode !== 'inline') {
|
|
||||||
this.switchModeFromInline = true
|
this.switchModeFromInline = true
|
||||||
}
|
}
|
||||||
if (hasProp(this, 'openKeys')) {
|
if (hasProp(this, 'openKeys')) {
|
||||||
this.setState({ sOpenKeys: nextProps.openKeys })
|
this.setState({ sOpenKeys: nextProps.openKeys })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ((nextProps.inlineCollapsed && !preProps.inlineCollapsed) ||
|
if (nextProps.inlineCollapsed && !preProps.inlineCollapsed) {
|
||||||
(layoutContext.siderCollapsed && !preLayoutContext.siderCollapsed)) {
|
|
||||||
this.switchModeFromInline =
|
this.switchModeFromInline =
|
||||||
!!this.state.openKeys.length && !!this.$el.querySelectorAll(`.${prefixCls}-submenu-open`).length
|
!!sOpenKeys.length && !!this.$el.querySelectorAll(`.${prefixCls}-submenu-open`).length
|
||||||
this.inlineOpenKeys = this.state.openKeys
|
this.inlineOpenKeys = sOpenKeys
|
||||||
this.setState({ sOpenKeys: [] })
|
this.setState({ sOpenKeys: [] })
|
||||||
}
|
}
|
||||||
if ((!nextProps.inlineCollapsed && preProps.inlineCollapsed) ||
|
|
||||||
(!layoutContext.siderCollapsed && preLayoutContext.siderCollapsed)) {
|
if (!nextProps.inlineCollapsed && preProps.inlineCollapsed) {
|
||||||
this.setState({ sOpenKeys: this.inlineOpenKeys })
|
this.setState({ sOpenKeys: this.inlineOpenKeys })
|
||||||
this.inlineOpenKeys = []
|
this.inlineOpenKeys = []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
deep: true,
|
||||||
|
},
|
||||||
|
'layoutContext.siderCollapsed': function (val) {
|
||||||
|
const { openKeys, sOpenKeys, prefixCls } = this
|
||||||
|
if (hasProp(this, 'openKeys')) {
|
||||||
|
this.setState({ sOpenKeys: openKeys })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (val) {
|
||||||
|
this.switchModeFromInline =
|
||||||
|
!!sOpenKeys.length && !!this.$el.querySelectorAll(`.${prefixCls}-submenu-open`).length
|
||||||
|
this.inlineOpenKeys = sOpenKeys
|
||||||
|
this.setState({ sOpenKeys: [] })
|
||||||
|
} else {
|
||||||
|
this.setState({ sOpenKeys: this.inlineOpenKeys })
|
||||||
|
this.inlineOpenKeys = []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
const props = this.$props
|
const props = this.$props
|
||||||
warning(
|
warning(
|
||||||
|
@ -103,9 +116,18 @@ export default {
|
||||||
this.handleOpenChange([])
|
this.handleOpenChange([])
|
||||||
this.$emit('click', e)
|
this.$emit('click', e)
|
||||||
},
|
},
|
||||||
|
handleSelect (info) {
|
||||||
|
this.$emit('select', info)
|
||||||
|
this.$emit('selectChange', info.selectedKeys)
|
||||||
|
},
|
||||||
|
handleDeselect (info) {
|
||||||
|
this.$emit('deselect', info)
|
||||||
|
this.$emit('selectChange', info.selectedKeys)
|
||||||
|
},
|
||||||
handleOpenChange (openKeys) {
|
handleOpenChange (openKeys) {
|
||||||
this.setOpenKeys(openKeys)
|
this.setOpenKeys(openKeys)
|
||||||
this.$emit('openChange', openKeys)
|
this.$emit('openChange', openKeys)
|
||||||
|
this.$emit('update:openKeys', openKeys)
|
||||||
},
|
},
|
||||||
setOpenKeys (openKeys) {
|
setOpenKeys (openKeys) {
|
||||||
if (!hasProp(this, 'openKeys')) {
|
if (!hasProp(this, 'openKeys')) {
|
||||||
|
@ -148,7 +170,7 @@ export default {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case 'inline':
|
case 'inline':
|
||||||
menuOpenAnimation = {
|
menuOpenAnimation = { on: {
|
||||||
...animation,
|
...animation,
|
||||||
leave: (node, done) => animation.leave(node, () => {
|
leave: (node, done) => animation.leave(node, () => {
|
||||||
// Make sure inline menu leave animation finished before mode is switched
|
// Make sure inline menu leave animation finished before mode is switched
|
||||||
|
@ -162,7 +184,7 @@ export default {
|
||||||
}
|
}
|
||||||
done()
|
done()
|
||||||
}),
|
}),
|
||||||
}
|
}}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
@ -171,7 +193,7 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
render () {
|
render () {
|
||||||
const { $props, layoutContext, $slots } = this
|
const { $props, layoutContext, $slots, $listeners } = this
|
||||||
const { collapsedWidth, siderCollapsed } = layoutContext
|
const { collapsedWidth, siderCollapsed } = layoutContext
|
||||||
this.preProps = cloneDeep($props)
|
this.preProps = cloneDeep($props)
|
||||||
this.preLayoutContext = {
|
this.preLayoutContext = {
|
||||||
|
@ -194,9 +216,14 @@ export default {
|
||||||
mode: menuMode,
|
mode: menuMode,
|
||||||
},
|
},
|
||||||
on: {
|
on: {
|
||||||
|
...$listeners,
|
||||||
|
select: this.handleSelect,
|
||||||
|
deselect: this.handleDeselect,
|
||||||
openChange: this.handleOpenChange,
|
openChange: this.handleOpenChange,
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
if (!hasProp(this, 'selectedKeys')) {
|
||||||
|
delete menuProps.props.selectedKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
if (menuMode !== 'inline') {
|
if (menuMode !== 'inline') {
|
||||||
|
|
|
@ -40,7 +40,7 @@ const Menu = {
|
||||||
if (hasProp(this, 'selectedKeys')) {
|
if (hasProp(this, 'selectedKeys')) {
|
||||||
props.sSelectedKeys = nextProps.selectedKeys || []
|
props.sSelectedKeys = nextProps.selectedKeys || []
|
||||||
}
|
}
|
||||||
if (hasProp(this, 'selectedKeys')) {
|
if (hasProp(this, 'openKeys')) {
|
||||||
props.sOpenKeys = nextProps.openKeys || []
|
props.sOpenKeys = nextProps.openKeys || []
|
||||||
}
|
}
|
||||||
this.setState(props)
|
this.setState(props)
|
||||||
|
@ -81,7 +81,7 @@ const Menu = {
|
||||||
}
|
}
|
||||||
this.__emit('select', {
|
this.__emit('select', {
|
||||||
...selectInfo,
|
...selectInfo,
|
||||||
sSelectedKeys,
|
selectedKeys: sSelectedKeys,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -139,7 +139,7 @@ const Menu = {
|
||||||
}
|
}
|
||||||
this.__emit('deselect', {
|
this.__emit('deselect', {
|
||||||
...selectInfo,
|
...selectInfo,
|
||||||
sSelectedKeys,
|
selectedKeys: sSelectedKeys,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -451,7 +451,6 @@ export default {
|
||||||
animProps.name = openTransitionName
|
animProps.name = openTransitionName
|
||||||
} else if (typeof openAnimation === 'object') {
|
} else if (typeof openAnimation === 'object') {
|
||||||
animProps = { ...animProps, ...openAnimation.props || {}}
|
animProps = { ...animProps, ...openAnimation.props || {}}
|
||||||
animProps.on = openAnimation.on
|
|
||||||
if (!transitionAppear) {
|
if (!transitionAppear) {
|
||||||
animProps.appear = false
|
animProps.appear = false
|
||||||
}
|
}
|
||||||
|
|
|
@ -333,16 +333,8 @@ export default {
|
||||||
|
|
||||||
getContainer () {
|
getContainer () {
|
||||||
const { $props: props } = this
|
const { $props: props } = this
|
||||||
// const popupContainer = document.createElement('div')
|
|
||||||
// // Make sure default popup container will never cause scrollbar appearing
|
|
||||||
// // https://github.com/react-component/trigger/issues/41
|
|
||||||
// popupContainer.style.position = 'absolute'
|
|
||||||
// popupContainer.style.top = '0'
|
|
||||||
// popupContainer.style.left = '0'
|
|
||||||
// popupContainer.style.width = '100%'
|
|
||||||
const mountNode = props.getPopupContainer
|
const mountNode = props.getPopupContainer
|
||||||
? props.getPopupContainer(this.$el) : props.getDocument().body
|
? props.getPopupContainer(this.$el) : props.getDocument().body
|
||||||
// mountNode.appendChild(popupContainer)
|
|
||||||
return mountNode
|
return mountNode
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -515,13 +507,6 @@ export default {
|
||||||
this._component = null
|
this._component = null
|
||||||
}
|
}
|
||||||
newChildProps.addChildren = this._component
|
newChildProps.addChildren = this._component
|
||||||
// // 复制一份事件,防止cloneElement
|
|
||||||
// if (child.componentOptions && child.componentOptions.listeners) {
|
|
||||||
// console.log(child.componentOptions.listeners)
|
|
||||||
// child.componentOptions.listeners = { ...child.componentOptions.listeners }
|
|
||||||
// } else if (child.data && child.data.on) {
|
|
||||||
// child.data.on = { ...child.data.on }
|
|
||||||
// }
|
|
||||||
const trigger = cloneElement(child, newChildProps)
|
const trigger = cloneElement(child, newChildProps)
|
||||||
return trigger
|
return trigger
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue