diff --git a/components/_util/vnode.js b/components/_util/vnode.js index bde73fa43..cddf92fcf 100644 --- a/components/_util/vnode.js +++ b/components/_util/vnode.js @@ -33,6 +33,7 @@ export function cloneVNodes (vnodes, deep) { export function cloneElement (node, nodeProps) { const { props, key } = nodeProps if (node.componentOptions) { + node.componentOptions.propsData = node.componentOptions.propsData || {} Object.assign(node.componentOptions.propsData, props) } const data = node.data || {} @@ -44,6 +45,7 @@ export function cloneElement (node, nodeProps) { node.data = Object.assign(data, { style, attrs, class: cls, on }) if (key !== undefined) { node.key = key + node.data.key = key } return node } diff --git a/components/menu/src/Menu.vue b/components/menu/src/Menu.vue index 5d77bf48e..a4e16beb6 100644 --- a/components/menu/src/Menu.vue +++ b/components/menu/src/Menu.vue @@ -18,7 +18,7 @@ const Menu = { subMenuOpenDelay: PropTypes.number.def(0), subMenuCloseDelay: PropTypes.number.def(0.1), forceSubMenuRender: PropTypes.bool, - triggerSubMenuAction: PropTypes.string.def('hover'), + triggerSubMenuAction: PropTypes.string.def('click'), level: PropTypes.number.def(1), selectable: PropTypes.bool.def(true), multiple: PropTypes.bool, @@ -183,6 +183,7 @@ const Menu = { openKeys: state.sOpenKeys, selectedKeys: state.sSelectedKeys, triggerSubMenuAction: this.$props.triggerSubMenuAction, + isRootMenu: true, } return this.renderCommonMenuItem(c, i, subIndex, extraProps) }, @@ -191,7 +192,7 @@ const Menu = { render () { const props = { ...this.$props } props.class = ` ${props.prefixCls}-root` - return this.renderRoot(props) + return this.renderRoot(props, this.$slots.default) }, } export default Menu diff --git a/components/menu/src/MenuItem.vue b/components/menu/src/MenuItem.vue index daae53721..fdfdc9d4e 100644 --- a/components/menu/src/MenuItem.vue +++ b/components/menu/src/MenuItem.vue @@ -1,6 +1,7 @@ diff --git a/components/menu/src/MenuItemGroup.vue b/components/menu/src/MenuItemGroup.vue index 638b18f2c..2994a06fa 100644 --- a/components/menu/src/MenuItemGroup.vue +++ b/components/menu/src/MenuItemGroup.vue @@ -12,7 +12,11 @@ const MenuItemGroup = { disabled: PropTypes.bool.def(true), title: PropTypes.any.def(''), }, - + data () { + return { + isMenuItemGroup: true, + } + }, methods: { renderInnerMenuItem (item, subIndex) { const { renderMenuItem, index } = this.$props @@ -40,7 +44,5 @@ const MenuItemGroup = { }, } -MenuItemGroup.isMenuItemGroup = true - export default MenuItemGroup diff --git a/components/menu/src/MenuMixin.js b/components/menu/src/MenuMixin.js index 01b17bf96..abd920d5a 100644 --- a/components/menu/src/MenuMixin.js +++ b/components/menu/src/MenuMixin.js @@ -46,8 +46,9 @@ function getActiveKey (props, originalActiveKey) { return activeKey } -const MenuMixin = { +export default { props: { + test: PropTypes.any, prefixCls: PropTypes.string.def('rc-menu'), inlineIndent: PropTypes.number.def(24), focusable: PropTypes.bool.def(true), @@ -59,6 +60,7 @@ const MenuMixin = { defaultSelectedKeys: PropTypes.arrayOf(PropTypes.string), defaultOpenKeys: PropTypes.arrayOf(PropTypes.string), openKeys: PropTypes.arrayOf(PropTypes.string), + mode: PropTypes.oneOf(['horizontal', 'vertical', 'vertical-left', 'vertical-right', 'inline']).def('vertical'), }, mixin: [StateMixin], data () { @@ -186,7 +188,7 @@ const MenuMixin = { renderMenuItem: this.renderMenuItem, rootPrefixCls: props.prefixCls, index: i, - parentMenu: this, + // parentMenu: this, eventKey: key, active: !childProps.disabled && isActive, multiple: props.multiple, @@ -201,24 +203,27 @@ const MenuMixin = { on: { click: this.onClick, itemHover: this.onItemHover, - // openChange: () => { console.log('openChange') }, + openChange: () => { console.log('openChange') }, deselect: this.onDeselect, destroy: this.onDestroy, select: this.onSelect, }, - - ref: childProps.disabled ? undefined : child.ref, + // ref: childProps.disabled ? undefined : child.ref, // ref: childProps.disabled ? undefined // : createChainedFunction(child.ref, saveRef.bind(this, i, subIndex)), } - !childProps.disabled && this.saveRef(i, subIndex, child.ref) + // !childProps.disabled && this.saveRef(i, subIndex, child.ref) if (props.mode === 'inline') { newChildProps.props.triggerSubMenuAction = 'click' } + if (!extraProps.isRootMenu) { + newChildProps.props.clearSubMenuTimers = this.clearSubMenuTimers + } + // return this.$scopedSlots.default(newChildProps) return cloneElement(child, newChildProps) }, - renderRoot (props) { + renderRoot (props, children = []) { this.instanceArray = [] const className = { [props.prefixCls]: true, @@ -237,7 +242,6 @@ const MenuMixin = { }, class: className, on: {}, - // style:props.style, } if (props.id) { domProps.id = props.id @@ -246,15 +250,13 @@ const MenuMixin = { domProps.attrs.tabIndex = '0' domProps.on.keydown = this.onKeyDown } + const newChildren = children.map(this.renderMenuItem) return ( - // ESLint is not smart enough to know that the type of `children` was checked. - /* eslint-disable */ - {this.$slots.default.map(this.renderMenuItem)} + {newChildren} - /*eslint -enable */ ) }, @@ -301,5 +303,3 @@ const MenuMixin = { }, }, } - -export default MenuMixin diff --git a/components/menu/src/SubMenu.vue b/components/menu/src/SubMenu.vue index 84e469679..0242e6f25 100644 --- a/components/menu/src/SubMenu.vue +++ b/components/menu/src/SubMenu.vue @@ -4,7 +4,7 @@ import Trigger from '../../trigger' import KeyCode from '../../_util/KeyCode' import SubPopupMenu from './SubPopupMenu' import placements from './placements' -import { loopMenuItemRecusively } from './util' +import { loopMenuItemRecusively, noop } from './util' import StateMixin from '../../_util/StateMixin' let guid = 0 @@ -16,26 +16,27 @@ const popupPlacementMap = { 'vertical-right': 'leftTop', } -const SubMenu = { +export default { name: 'SubMenu', props: { - parentMenu: PropTypes.object, mode: PropTypes.oneOf(['horizontal', 'vertical', 'vertical-left', 'vertical-right', 'inline']).def('vertical'), title: PropTypes.any.def(''), - children: PropTypes.any, - selectedKeys: PropTypes.array, - openKeys: PropTypes.array, + selectedKeys: PropTypes.array.def([]), + openKeys: PropTypes.array.def([]), // onClick: PropTypes.func, - openChange: PropTypes.func, + openChange: PropTypes.func.def(noop), rootPrefixCls: PropTypes.string, eventKey: PropTypes.string, multiple: PropTypes.bool, active: PropTypes.bool, // TODO: remove + isRootMenu: PropTypes.bool, // onItemHover: PropTypes.func, // onSelect: PropTypes.func, triggerSubMenuAction: PropTypes.string, popupClassName: PropTypes.string, + getPopupContainer: PropTypes.func, + test: PropTypes.any, // onDeselect: PropTypes.func, // onDestroy: PropTypes.func, // onMouseEnter: PropTypes.func, @@ -46,13 +47,19 @@ const SubMenu = { }, mixins: [StateMixin], data () { - this.isSubMenu = 1 - this.isRootMenu = false return { defaultActiveFirst: false, + isSubMenu: 1, } }, - + watch: { + '$props': { + handler: function (nextProps) { + console.log(nextProps) + }, + deep: true, + }, + }, mounted () { this.handleUpdated() }, @@ -62,16 +69,14 @@ const SubMenu = { }, beforeDestroy () { - const { eventKey, parentMenu } = this.$props + const { eventKey } = this.$props this.$emit('destroy', eventKey) - if (parentMenu.subMenuInstance === this) { - this.clearSubMenuTimers() - } + this.clearSubMenuTimers() }, methods: { handleUpdated () { - const { mode, parentMenu } = this.$props - if (mode !== 'horizontal' || !parentMenu.isRootMenu || !this.isOpen()) { + const { mode, isRootMenu } = this.$props + if (mode !== 'horizontal' || !isRootMenu || !this.isOpen()) { return } setTimeout(() => { @@ -155,11 +160,9 @@ const SubMenu = { onMouseLeave (e) { const { - parentMenu, eventKey, } = this.$props - parentMenu.subMenuInstance = this - parentMenu.subMenuLeaveFn = () => { + this.subMenuLeaveFn = () => { // trigger mouseleave this.$emit('mouseleave', { key: eventKey, @@ -168,7 +171,7 @@ const SubMenu = { } // prevent popup menu and submenu gap - parentMenu.subMenuLeaveTimer = setTimeout(parentMenu.subMenuLeaveFn, 100) + this.subMenuLeaveTimer = setTimeout(this.subMenuLeaveFn, 100) }, onTitleMouseEnter (domEvent) { @@ -185,9 +188,8 @@ const SubMenu = { }, onTitleMouseLeave (e) { - const { parentMenu, eventKey } = this.$props - parentMenu.subMenuInstance = this - parentMenu.subMenuTitleLeaveFn = () => { + const { eventKey } = this.$props + this.subMenuTitleLeaveFn = () => { this.$emit('itemHover', { key: eventKey, hover: false, @@ -197,7 +199,7 @@ const SubMenu = { domEvent: e, }) } - parentMenu.subMenuTitleLeaveTimer = setTimeout(parentMenu.subMenuTitleLeaveFn, 100) + this.subMenuTitleLeaveTimer = setTimeout(this.subMenuTitleLeaveFn, 100) }, onTitleClick (e) { @@ -272,20 +274,18 @@ const SubMenu = { }, clearSubMenuTitleLeaveTimer () { - const parentMenu = this.$props.parentMenu - if (parentMenu.subMenuTitleLeaveTimer) { - clearTimeout(parentMenu.subMenuTitleLeaveTimer) - parentMenu.subMenuTitleLeaveTimer = null - parentMenu.subMenuTitleLeaveFn = null + if (this.subMenuTitleLeaveTimer) { + clearTimeout(this.subMenuTitleLeaveTimer) + this.subMenuTitleLeaveTimer = null + this.subMenuTitleLeaveFn = null } }, clearSubMenuLeaveTimer () { - const parentMenu = this.$props.parentMenu - if (parentMenu.subMenuLeaveTimer) { - clearTimeout(parentMenu.subMenuLeaveTimer) - parentMenu.subMenuLeaveTimer = null - parentMenu.subMenuLeaveFn = null + if (this.subMenuLeaveTimer) { + clearTimeout(this.subMenuLeaveTimer) + this.subMenuLeaveTimer = null + this.subMenuLeaveFn = null } }, @@ -319,6 +319,7 @@ const SubMenu = { defaultActiveFirst: this.$data.defaultActiveFirst, multiple: props.multiple, prefixCls: props.rootPrefixCls, + clearSubMenuTimers: this.clearSubMenuTimers, }, on: { click: this.onSubMenuClick, @@ -404,24 +405,24 @@ const SubMenu = { ) const children = this.renderChildren(this.$slots.default) - const getPopupContainer = props.parentMenu.isRootMenu - ? props.parentMenu.getPopupContainer : triggerNode => triggerNode.parentNode + const getPopupContainer = this.isRootMenu + ? this.getPopupContainer : triggerNode => triggerNode.parentNode const popupPlacement = popupPlacementMap[props.mode] const popupClassName = props.mode === 'inline' ? '' : props.popupClassName const liProps = { on: { ...mouseEvents }, class: className, } - console.log(isOpen) return (
  • {isInlineMode && title} {isInlineMode && children} {!isInlineMode && ( + diff --git a/components/menu/src/SubPopupMenu.vue b/components/menu/src/SubPopupMenu.vue index 2e111b797..c534c7ada 100644 --- a/components/menu/src/SubPopupMenu.vue +++ b/components/menu/src/SubPopupMenu.vue @@ -5,57 +5,57 @@ import MenuMixin from './MenuMixin' export default { name: 'SubPopupMenu', props: { - onSelect: PropTypes.func, - onClick: PropTypes.func, - onDeselect: PropTypes.func, - onOpenChange: PropTypes.func, - onDestroy: PropTypes.func, + // onSelect: PropTypes.func, + // onClick: PropTypes.func, + // onDeselect: PropTypes.func, + // onOpenChange: PropTypes.func, + // onDestroy: PropTypes.func, openTransitionName: PropTypes.string, openAnimation: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), openKeys: PropTypes.arrayOf(PropTypes.string), visible: PropTypes.bool, - children: PropTypes.any, }, mixins: [MenuMixin], + methods: { + onDeselect (selectInfo) { + this.$emit('deselect', selectInfo) + }, - onDeselect (selectInfo) { - this.$emit('deselect', selectInfo) + onSelect (selectInfo) { + this.$emit('select', selectInfo) + }, + + onClick (e) { + this.$emit('click', e) + }, + + onOpenChange (e) { + this.$emit('openChange', e) + }, + + onDestroy (key) { + this.$$emit('destroy', key) + }, + + getOpenTransitionName () { + return this.$props.openTransitionName + }, + + renderMenuItem (c, i, subIndex) { + if (!c) { + return null + } + const props = this.$props + const extraProps = { + openKeys: props.openKeys, + selectedKeys: props.selectedKeys, + triggerSubMenuAction: props.triggerSubMenuAction, + isRootMenu: false, + } + return this.renderCommonMenuItem(c, i, subIndex, extraProps) + }, }, - - onSelect (selectInfo) { - this.$emit('select', selectInfo) - }, - - onClick (e) { - this.$emit('click', e) - }, - - onOpenChange (e) { - this.$emit('openChange', e) - }, - - onDestroy (key) { - this.$$emit('destroy', key) - }, - - getOpenTransitionName () { - return this.$props.openTransitionName - }, - - renderMenuItem (c, i, subIndex) { - if (!c) { - return null - } - const props = this.$props - const extraProps = { - openKeys: props.openKeys, - selectedKeys: props.selectedKeys, - triggerSubMenuAction: props.triggerSubMenuAction, - } - return this.renderCommonMenuItem(c, i, subIndex, extraProps) - }, - render () { const props = { ...this.$props } @@ -69,7 +69,7 @@ export default { const transitionAppear = !(!haveRendered && props.visible && props.mode === 'inline') - props.className += ` ${props.prefixCls}-sub` + props.class = `${props.prefixCls}-sub` const animProps = {} if (props.openTransitionName) { animProps.transitionName = props.openTransitionName @@ -84,7 +84,7 @@ export default { appear name={animProps.transitionName} > - {this.renderRoot(props)} + {this.renderRoot(props, this.$slots.default)} ) }, diff --git a/components/menu/src/util.js b/components/menu/src/util.js index 520b3cbd1..396d20bc5 100644 --- a/components/menu/src/util.js +++ b/components/menu/src/util.js @@ -30,6 +30,7 @@ export function loopMenuItemRecusively (children, keys, ret) { return } if (c) { + console.log(c) const construt = c.type if (!construt || !(construt.isSubMenu || construt.isMenuItem || construt.isMenuItemGroup)) { return diff --git a/components/trigger/Popup.vue b/components/trigger/Popup.vue index 83268962b..7ff3e0c4f 100644 --- a/components/trigger/Popup.vue +++ b/components/trigger/Popup.vue @@ -19,6 +19,7 @@ export default { maskTransitionName: PropTypes.string, mask: PropTypes.bool, zIndex: PropTypes.number, + popupClassName: PropTypes.any, }, data () { return { @@ -81,7 +82,7 @@ export default { }, getClassName (currentAlignClassName) { - return `${this.$props.prefixCls} ${currentAlignClassName}` + return `${this.$props.prefixCls} ${this.$props.popupClassName} ${currentAlignClassName}` }, onMouseEnter (e) { this.$emit('mouseenter', e) @@ -112,7 +113,7 @@ export default { prefixCls, visible, }, - class: className, + class: `${className}`, on: { mouseenter: onMouseEnter, mouseleave: onMouseLeave, @@ -142,7 +143,6 @@ export default { {$slots.default} - ) }, @@ -189,7 +189,8 @@ export default { return (
    {getMaskElement()} - {destroyPopup ? null : getPopupElement()} + { destroyPopup + ? null : getPopupElement()}
    ) }, diff --git a/components/trigger/index.vue b/components/trigger/index.vue index 2b048a781..355a62b6d 100644 --- a/components/trigger/index.vue +++ b/components/trigger/index.vue @@ -314,6 +314,7 @@ export default { maskAnimation, maskTransitionName, getContainer, + popupClassName, }, on: { align: onPopupAlign, @@ -321,7 +322,6 @@ export default { }, ref: 'popup', style: popupStyle, - class: popupClassName, } return (