add menu demo

pull/9/head
tangjinzhou 2018-01-17 19:15:18 +08:00
parent 3af108ffcb
commit f9a85a6c41
8 changed files with 165 additions and 69 deletions

View File

@ -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 }
} }

View File

@ -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}

View File

@ -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,

View 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>

View File

@ -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') {

View File

@ -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,
}) })
} }
}, },

View File

@ -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
} }

View File

@ -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
}, },