Browse Source

add menu demo

pull/9/head
tangjinzhou 7 years ago
parent
commit
f9a85a6c41
  1. 4
      components/_util/vnode.js
  2. 19
      components/menu/MenuItem.vue
  3. 15
      components/menu/demo/horizontal.vue
  4. 81
      components/menu/demo/inline-collapsed.vue
  5. 93
      components/menu/index.vue
  6. 6
      components/menu/src/Menu.vue
  7. 1
      components/menu/src/SubMenu.vue
  8. 15
      components/trigger/index.vue

4
components/_util/vnode.js

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

19
components/menu/MenuItem.vue

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

15
components/menu/demo/horizontal.vue

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

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

93
components/menu/index.vue

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

6
components/menu/src/Menu.vue

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

1
components/menu/src/SubMenu.vue

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

15
components/trigger/index.vue

@ -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…
Cancel
Save