mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-12-02 03:58:05 +08:00
add menu demo
This commit is contained in:
parent
3af108ffcb
commit
f9a85a6c41
@ -48,7 +48,7 @@ export function cloneElement (n, nodeProps, clone) {
|
||||
attrs = data.attrs,
|
||||
ref,
|
||||
} = nodeProps
|
||||
node.data = Object.assign(data, { style, attrs, class: cls })
|
||||
node.data = Object.assign({}, data, { style, attrs, class: cls })
|
||||
if (node.componentOptions) {
|
||||
node.componentOptions.propsData = node.componentOptions.propsData || {}
|
||||
node.componentOptions.listeners = node.componentOptions.listeners || {}
|
||||
@ -96,5 +96,5 @@ export function getEvents (child) {
|
||||
} else if (child.data && child.data.on) {
|
||||
events = child.data.on
|
||||
}
|
||||
return events
|
||||
return { ...events }
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import { getComponentFromProp } from '../_util/props-util'
|
||||
export default {
|
||||
props: itemProps,
|
||||
inject: {
|
||||
inlineCollapsed: { default: false },
|
||||
getInlineCollapsed: { default: () => { false } },
|
||||
},
|
||||
isMenuItem: 1,
|
||||
methods: {
|
||||
@ -16,20 +16,27 @@ export default {
|
||||
},
|
||||
},
|
||||
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 = {
|
||||
props,
|
||||
attrs,
|
||||
on: $listeners,
|
||||
on: { ...$listeners },
|
||||
class: getClass(this),
|
||||
style: getStyle(this),
|
||||
}
|
||||
const toolTipProps = {
|
||||
props: {
|
||||
placement: 'right',
|
||||
overlayClassName: `${props.rootPrefixCls}-inline-collapsed-tooltip`,
|
||||
},
|
||||
on: {},
|
||||
}
|
||||
return <Tooltip
|
||||
placement='right'
|
||||
overlayClassName={`${props.rootPrefixCls}-inline-collapsed-tooltip`}
|
||||
{...toolTipProps}
|
||||
>
|
||||
<template slot='title'>
|
||||
{inlineCollapsed && props.level === 1 ? $slots.default : ''}
|
||||
{inlineCollapsed && props.level === 1 ? <span>$slots</span> : ''}
|
||||
</template>
|
||||
<Item {...itemProps} ref='menuItem'>
|
||||
{$slots.default}
|
||||
|
@ -1,8 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<md>
|
||||
## 顶部导航
|
||||
水平的顶部导航菜单。
|
||||
</md>
|
||||
<Menu
|
||||
@click="handleClick"
|
||||
:selectedKeys="[current]"
|
||||
v-model="current"
|
||||
mode="horizontal"
|
||||
>
|
||||
<MenuItem key="mail">
|
||||
@ -38,15 +41,9 @@ const MenuItem = Menu.Item
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
current: 'mail',
|
||||
current: ['mail'],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick (e) {
|
||||
console.log(e)
|
||||
this.current = e.key
|
||||
},
|
||||
},
|
||||
components: {
|
||||
Menu,
|
||||
Icon,
|
||||
|
81
components/menu/demo/inline-collapsed.vue
Normal file
81
components/menu/demo/inline-collapsed.vue
Normal file
@ -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 = {
|
||||
theme: PropTypes.oneOf(['light', 'dark']).def('light'),
|
||||
mode: MenuMode,
|
||||
mode: MenuMode.def('vertical'),
|
||||
selectable: PropTypes.bool,
|
||||
selectedKeys: PropTypes.arrayOf(PropTypes.string),
|
||||
defaultSelectedKeys: PropTypes.array,
|
||||
openKeys: 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]),
|
||||
openTransitionName: PropTypes.string,
|
||||
prefixCls: PropTypes.string.def('ant-menu'),
|
||||
@ -40,6 +36,7 @@ export default {
|
||||
provide () {
|
||||
return {
|
||||
inlineCollapsed: this.getInlineCollapsed(),
|
||||
getInlineCollapsed: this.getInlineCollapsed,
|
||||
antdMenuTheme: this.$props.theme,
|
||||
}
|
||||
},
|
||||
@ -47,37 +44,53 @@ export default {
|
||||
inject: {
|
||||
layoutContext: { default: {}},
|
||||
},
|
||||
model: {
|
||||
prop: 'selectedKeys',
|
||||
event: 'selectChange',
|
||||
},
|
||||
watch: {
|
||||
'$props': {
|
||||
handler: function (nextProps) {
|
||||
const { preProps, sOpenKeys } = this
|
||||
const { prefixCls } = preProps
|
||||
if (preProps.mode === 'inline' && nextProps.mode !== 'inline') {
|
||||
this.switchModeFromInline = true
|
||||
}
|
||||
if (hasProp(this, 'openKeys')) {
|
||||
this.setState({ sOpenKeys: nextProps.openKeys })
|
||||
return
|
||||
}
|
||||
if (nextProps.inlineCollapsed && !preProps.inlineCollapsed) {
|
||||
this.switchModeFromInline =
|
||||
!!sOpenKeys.length && !!this.$el.querySelectorAll(`.${prefixCls}-submenu-open`).length
|
||||
this.inlineOpenKeys = sOpenKeys
|
||||
this.setState({ sOpenKeys: [] })
|
||||
}
|
||||
|
||||
if (!nextProps.inlineCollapsed && preProps.inlineCollapsed) {
|
||||
this.setState({ sOpenKeys: this.inlineOpenKeys })
|
||||
this.inlineOpenKeys = []
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
beforeUpdate () {
|
||||
const { preProps, $props: nextProps, layoutContext, preLayoutContext = {}} = this
|
||||
const { prefixCls } = preProps
|
||||
if (preProps.mode === 'inline' &&
|
||||
nextProps.mode !== 'inline') {
|
||||
this.switchModeFromInline = true
|
||||
}
|
||||
if (hasProp(this, 'openKeys')) {
|
||||
this.setState({ sOpenKeys: nextProps.openKeys })
|
||||
return
|
||||
}
|
||||
if ((nextProps.inlineCollapsed && !preProps.inlineCollapsed) ||
|
||||
(layoutContext.siderCollapsed && !preLayoutContext.siderCollapsed)) {
|
||||
this.switchModeFromInline =
|
||||
!!this.state.openKeys.length && !!this.$el.querySelectorAll(`.${prefixCls}-submenu-open`).length
|
||||
this.inlineOpenKeys = this.state.openKeys
|
||||
this.setState({ sOpenKeys: [] })
|
||||
}
|
||||
if ((!nextProps.inlineCollapsed && preProps.inlineCollapsed) ||
|
||||
(!layoutContext.siderCollapsed && preLayoutContext.siderCollapsed)) {
|
||||
this.setState({ sOpenKeys: this.inlineOpenKeys })
|
||||
this.inlineOpenKeys = []
|
||||
}
|
||||
'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 () {
|
||||
const props = this.$props
|
||||
@ -103,9 +116,18 @@ export default {
|
||||
this.handleOpenChange([])
|
||||
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) {
|
||||
this.setOpenKeys(openKeys)
|
||||
this.$emit('openChange', openKeys)
|
||||
this.$emit('update:openKeys', openKeys)
|
||||
},
|
||||
setOpenKeys (openKeys) {
|
||||
if (!hasProp(this, 'openKeys')) {
|
||||
@ -148,7 +170,7 @@ export default {
|
||||
}
|
||||
break
|
||||
case 'inline':
|
||||
menuOpenAnimation = {
|
||||
menuOpenAnimation = { on: {
|
||||
...animation,
|
||||
leave: (node, done) => animation.leave(node, () => {
|
||||
// Make sure inline menu leave animation finished before mode is switched
|
||||
@ -162,7 +184,7 @@ export default {
|
||||
}
|
||||
done()
|
||||
}),
|
||||
}
|
||||
}}
|
||||
break
|
||||
default:
|
||||
}
|
||||
@ -171,7 +193,7 @@ export default {
|
||||
},
|
||||
},
|
||||
render () {
|
||||
const { $props, layoutContext, $slots } = this
|
||||
const { $props, layoutContext, $slots, $listeners } = this
|
||||
const { collapsedWidth, siderCollapsed } = layoutContext
|
||||
this.preProps = cloneDeep($props)
|
||||
this.preLayoutContext = {
|
||||
@ -194,9 +216,14 @@ export default {
|
||||
mode: menuMode,
|
||||
},
|
||||
on: {
|
||||
...$listeners,
|
||||
select: this.handleSelect,
|
||||
deselect: this.handleDeselect,
|
||||
openChange: this.handleOpenChange,
|
||||
},
|
||||
|
||||
}
|
||||
if (!hasProp(this, 'selectedKeys')) {
|
||||
delete menuProps.props.selectedKeys
|
||||
}
|
||||
|
||||
if (menuMode !== 'inline') {
|
||||
|
@ -40,7 +40,7 @@ const Menu = {
|
||||
if (hasProp(this, 'selectedKeys')) {
|
||||
props.sSelectedKeys = nextProps.selectedKeys || []
|
||||
}
|
||||
if (hasProp(this, 'selectedKeys')) {
|
||||
if (hasProp(this, 'openKeys')) {
|
||||
props.sOpenKeys = nextProps.openKeys || []
|
||||
}
|
||||
this.setState(props)
|
||||
@ -81,7 +81,7 @@ const Menu = {
|
||||
}
|
||||
this.__emit('select', {
|
||||
...selectInfo,
|
||||
sSelectedKeys,
|
||||
selectedKeys: sSelectedKeys,
|
||||
})
|
||||
}
|
||||
},
|
||||
@ -139,7 +139,7 @@ const Menu = {
|
||||
}
|
||||
this.__emit('deselect', {
|
||||
...selectInfo,
|
||||
sSelectedKeys,
|
||||
selectedKeys: sSelectedKeys,
|
||||
})
|
||||
}
|
||||
},
|
||||
|
@ -451,7 +451,6 @@ export default {
|
||||
animProps.name = openTransitionName
|
||||
} else if (typeof openAnimation === 'object') {
|
||||
animProps = { ...animProps, ...openAnimation.props || {}}
|
||||
animProps.on = openAnimation.on
|
||||
if (!transitionAppear) {
|
||||
animProps.appear = false
|
||||
}
|
||||
|
@ -333,16 +333,8 @@ export default {
|
||||
|
||||
getContainer () {
|
||||
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
|
||||
? props.getPopupContainer(this.$el) : props.getDocument().body
|
||||
// mountNode.appendChild(popupContainer)
|
||||
return mountNode
|
||||
},
|
||||
|
||||
@ -515,13 +507,6 @@ export default {
|
||||
this._component = null
|
||||
}
|
||||
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)
|
||||
return trigger
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user