fix: menu parentMenu error
parent
d6a7c041b5
commit
60541d7d1b
|
@ -1 +1 @@
|
|||
Subproject commit e7feb6f5127f054c5ddac633b733369e182ab6f2
|
||||
Subproject commit a234ba5ccfe4ab14f1619ddc156aef5bf05a7f18
|
|
@ -1,3 +1,8 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`DropdownButton should support href like Button 1`] = `<div class="ant-btn-group ant-dropdown-button"><a href="https://ant.design" class="ant-btn ant-btn-default"></a><button type="button" class="ant-btn ant-btn-default ant-dropdown-trigger"><span role="img" aria-label="ellipsis" class="anticon anticon-ellipsis"><svg viewBox="64 64 896 896" focusable="false" data-icon="ellipsis" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z"></path></svg></span></button></div>`;
|
||||
exports[`DropdownButton should support href like Button 1`] = `
|
||||
<div class="ant-btn-group ant-dropdown-button"><a href="https://ant.design" class="ant-btn ant-btn-default">
|
||||
<!----></a>
|
||||
<!----><button class="ant-dropdown-trigger ant-btn ant-btn-default" type="button">
|
||||
<!----><span class="anticon anticon-ellipsis" role="img" aria-label="ellipsis"><svg class="" data-icon="ellipsis" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z"></path></svg></span></button></div>
|
||||
`;
|
||||
|
|
|
@ -11,36 +11,30 @@ describe('DropdownButton', () => {
|
|||
disabled: false,
|
||||
trigger: ['hover'],
|
||||
visible: true,
|
||||
onVisibleChange: () => {},
|
||||
};
|
||||
|
||||
const wrapper = mount(Dropdown.Button, {
|
||||
props,
|
||||
});
|
||||
const dropdownProps = wrapper.find({ name: 'ADropdown' }).props();
|
||||
|
||||
const dropdownProps = wrapper.findComponent({ name: 'ADropdown' }).props();
|
||||
Object.keys(props).forEach(key => {
|
||||
expect(dropdownProps[key]).toBe(props[key]);
|
||||
expect(dropdownProps[key]).toStrictEqual(props[key]);
|
||||
});
|
||||
});
|
||||
|
||||
it("don't pass visible to Dropdown if it's not exits", () => {
|
||||
const wrapper = mount({
|
||||
render() {
|
||||
return (
|
||||
<Dropdown.Button
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.Item>foo</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
/>
|
||||
);
|
||||
const wrapper = mount(Dropdown.Button, {
|
||||
props: {
|
||||
overlay: (
|
||||
<Menu>
|
||||
<Menu.Item>foo</Menu.Item>
|
||||
</Menu>
|
||||
),
|
||||
},
|
||||
});
|
||||
const dropdownProps = wrapper.find({ name: 'ADropdown' }).props();
|
||||
const dropdownProps = wrapper.findComponent({ name: 'ADropdown' }).props();
|
||||
|
||||
expect('visible' in dropdownProps).toBe(false);
|
||||
expect(dropdownProps.visible).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should support href like Button', () => {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { provide, inject } from 'vue';
|
||||
import Button from '../button';
|
||||
import classNames from 'classnames';
|
||||
import buttonTypes from '../button/buttonTypes';
|
||||
import { ButtonGroupProps } from '../button/button-group';
|
||||
import Dropdown from './dropdown';
|
||||
|
@ -24,10 +25,14 @@ const DropdownButtonProps = {
|
|||
placement: DropdownProps.placement.def('bottomRight'),
|
||||
icon: PropTypes.any,
|
||||
title: PropTypes.string,
|
||||
onClick: PropTypes.func,
|
||||
onVisibleChange: PropTypes.func,
|
||||
'onUpdate:visible': PropTypes.func,
|
||||
};
|
||||
export { DropdownButtonProps };
|
||||
export default {
|
||||
name: 'ADropdownButton',
|
||||
inheritAttrs: false,
|
||||
props: DropdownButtonProps,
|
||||
setup() {
|
||||
return {
|
||||
|
@ -41,10 +46,10 @@ export default {
|
|||
savePopupRef(ref) {
|
||||
this.popupRef = ref;
|
||||
},
|
||||
onClick(e) {
|
||||
handleClick(e) {
|
||||
this.$emit('click', e);
|
||||
},
|
||||
onVisibleChange(val) {
|
||||
handleVisibleChange(val) {
|
||||
this.$emit('update:visible', val);
|
||||
this.$emit('visibleChange', val);
|
||||
},
|
||||
|
@ -53,17 +58,21 @@ export default {
|
|||
const {
|
||||
type,
|
||||
disabled,
|
||||
onClick,
|
||||
htmlType,
|
||||
class: className,
|
||||
prefixCls: customizePrefixCls,
|
||||
overlay,
|
||||
trigger,
|
||||
align,
|
||||
visible,
|
||||
onVisibleChange,
|
||||
placement,
|
||||
getPopupContainer,
|
||||
href,
|
||||
title,
|
||||
...restProps
|
||||
} = this.$props;
|
||||
} = { ...this.$props, ...this.$attrs };
|
||||
const icon = getComponent(this, 'icon') || <EllipsisOutlined />;
|
||||
const { getPopupContainer: getContextPopupContainer } = this.configProvider;
|
||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
|
@ -74,7 +83,7 @@ export default {
|
|||
trigger: disabled ? [] : trigger,
|
||||
placement,
|
||||
getPopupContainer: getPopupContainer || getContextPopupContainer,
|
||||
onVisibleChange: this.onVisibleChange,
|
||||
onVisibleChange: this.handleVisibleChange,
|
||||
};
|
||||
if (hasProp(this, 'visible')) {
|
||||
dropdownProps.visible = visible;
|
||||
|
@ -82,7 +91,7 @@ export default {
|
|||
|
||||
const buttonGroupProps = {
|
||||
...restProps,
|
||||
class: prefixCls,
|
||||
class: classNames(prefixCls, className),
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -90,7 +99,7 @@ export default {
|
|||
<Button
|
||||
type={type}
|
||||
disabled={disabled}
|
||||
onClick={this.onClick}
|
||||
onClick={this.handleClick}
|
||||
htmlType={htmlType}
|
||||
href={href}
|
||||
title={title}
|
||||
|
|
|
@ -3,6 +3,7 @@ import RcDropdown from '../vc-dropdown/src/index';
|
|||
import DropdownButton from './dropdown-button';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { cloneElement } from '../_util/vnode';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
getOptionProps,
|
||||
getPropsData,
|
||||
|
@ -17,12 +18,14 @@ import RightOutlined from '@ant-design/icons-vue/RightOutlined';
|
|||
const DropdownProps = getDropdownProps();
|
||||
const Dropdown = {
|
||||
name: 'ADropdown',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
...DropdownProps,
|
||||
prefixCls: PropTypes.string,
|
||||
mouseEnterDelay: PropTypes.number.def(0.15),
|
||||
mouseLeaveDelay: PropTypes.number.def(0.1),
|
||||
placement: DropdownProps.placement.def('bottomLeft'),
|
||||
onVisibleChange: PropTypes.func,
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
|
@ -69,6 +72,10 @@ const Dropdown = {
|
|||
: overlay;
|
||||
return fixedModeOverlay;
|
||||
},
|
||||
handleVisibleChange(val) {
|
||||
this.$emit('update:visible', val);
|
||||
this.$emit('visibleChange', val);
|
||||
},
|
||||
},
|
||||
|
||||
render() {
|
||||
|
@ -78,14 +85,10 @@ const Dropdown = {
|
|||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('dropdown', customizePrefixCls);
|
||||
|
||||
const dropdownTrigger = cloneElement(
|
||||
getSlot(this),
|
||||
{
|
||||
class: `${prefixCls}-trigger`,
|
||||
disabled,
|
||||
},
|
||||
false,
|
||||
);
|
||||
const dropdownTrigger = cloneElement(getSlot(this), {
|
||||
class: classNames(this.$attrs?.class, `${prefixCls}-trigger`),
|
||||
disabled,
|
||||
});
|
||||
const triggerActions = disabled ? [] : trigger;
|
||||
let alignPoint;
|
||||
if (triggerActions && triggerActions.indexOf('contextmenu') !== -1) {
|
||||
|
@ -94,11 +97,13 @@ const Dropdown = {
|
|||
const dropdownProps = {
|
||||
alignPoint,
|
||||
...props,
|
||||
...this.$attrs,
|
||||
prefixCls,
|
||||
getPopupContainer: getPopupContainer || getContextPopupContainer,
|
||||
transitionName: this.getTransitionName(),
|
||||
trigger: triggerActions,
|
||||
overlay: this.renderOverlay(prefixCls),
|
||||
onVisibleChange: this.handleVisibleChange,
|
||||
};
|
||||
return <RcDropdown {...dropdownProps}>{dropdownTrigger}</RcDropdown>;
|
||||
},
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export default {
|
||||
name: 'MenuDivider',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
|
@ -9,6 +10,7 @@ export default {
|
|||
},
|
||||
render() {
|
||||
const { rootPrefixCls } = this.$props;
|
||||
return <li class={`${rootPrefixCls}-item-divider`} />;
|
||||
const { class: className = '', style } = this.$attrs;
|
||||
return <li class={`${className} ${rootPrefixCls}-item-divider`} style={style} />;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -4,6 +4,7 @@ import { default as SubPopupMenu, getActiveKey } from './SubPopupMenu';
|
|||
import BaseMixin from '../_util/BaseMixin';
|
||||
import hasProp, { getOptionProps, getComponent, filterEmpty } from '../_util/props-util';
|
||||
import commonPropsType from './commonPropsType';
|
||||
import { provide } from 'vue';
|
||||
|
||||
const Menu = {
|
||||
name: 'Menu',
|
||||
|
@ -35,6 +36,9 @@ const Menu = {
|
|||
// this.isRootMenu = true // 声明在props上
|
||||
return {};
|
||||
},
|
||||
created() {
|
||||
provide('parentMenu', this);
|
||||
},
|
||||
mounted() {
|
||||
this.updateMiniStore();
|
||||
},
|
||||
|
@ -166,7 +170,6 @@ const Menu = {
|
|||
expandIcon: getComponent(this, 'expandIcon', props),
|
||||
overflowedIndicator: getComponent(this, 'overflowedIndicator', props) || <span>···</span>,
|
||||
openTransitionName: this.getOpenTransitionName(),
|
||||
parentMenu: this,
|
||||
children: filterEmpty(props.children),
|
||||
onClick: this.onClick,
|
||||
onOpenChange: this.onOpenChange,
|
||||
|
|
|
@ -5,6 +5,7 @@ import scrollIntoView from 'dom-scroll-into-view';
|
|||
import { connect } from '../_util/store';
|
||||
import { noop, menuAllProps } from './util';
|
||||
import { getComponent, getSlot, findDOMNode } from '../_util/props-util';
|
||||
import { inject } from 'vue';
|
||||
|
||||
const props = {
|
||||
attribute: PropTypes.object,
|
||||
|
@ -18,7 +19,6 @@ const props = {
|
|||
inlineIndent: PropTypes.number.def(24),
|
||||
level: PropTypes.number.def(1),
|
||||
mode: PropTypes.oneOf(['horizontal', 'vertical', 'vertical-left', 'vertical-right', 'inline']),
|
||||
parentMenu: PropTypes.object,
|
||||
multiple: PropTypes.bool,
|
||||
value: PropTypes.any,
|
||||
isSelected: PropTypes.bool,
|
||||
|
@ -34,6 +34,9 @@ const MenuItem = {
|
|||
props,
|
||||
mixins: [BaseMixin],
|
||||
isMenuItem: true,
|
||||
setup() {
|
||||
return { parentMenu: inject('parentMenu', undefined) };
|
||||
},
|
||||
created() {
|
||||
this.prevActive = this.active;
|
||||
// invoke customized ref to expose component to mixin
|
||||
|
@ -41,9 +44,9 @@ const MenuItem = {
|
|||
},
|
||||
updated() {
|
||||
this.$nextTick(() => {
|
||||
const { active, parentMenu, eventKey } = this.$props;
|
||||
const { active, parentMenu, eventKey } = this;
|
||||
if (!this.prevActive && active && (!parentMenu || !parentMenu[`scrolled-${eventKey}`])) {
|
||||
scrollIntoView(this.$refs.node, findDOMNode(this.parentMenu), {
|
||||
scrollIntoView(findDOMNode(this.node), findDOMNode(parentMenu), {
|
||||
onlyScrollIfNeeded: true,
|
||||
});
|
||||
parentMenu[`scrolled-${eventKey}`] = true;
|
||||
|
@ -127,7 +130,9 @@ const MenuItem = {
|
|||
getDisabledClassName() {
|
||||
return `${this.getPrefixCls()}-disabled`;
|
||||
},
|
||||
|
||||
saveNode(node) {
|
||||
this.node = node;
|
||||
},
|
||||
callRef() {
|
||||
if (this.manualRef) {
|
||||
this.manualRef(this);
|
||||
|
@ -182,7 +187,7 @@ const MenuItem = {
|
|||
...props,
|
||||
...attrs,
|
||||
...mouseEvent,
|
||||
ref: 'node',
|
||||
ref: this.saveNode,
|
||||
};
|
||||
delete liProps.children;
|
||||
return (
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Transition } from 'vue';
|
||||
import { Transition, inject, provide } from 'vue';
|
||||
import omit from 'omit.js';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import Trigger from '../vc-trigger';
|
||||
|
@ -36,7 +36,6 @@ const SubMenu = {
|
|||
name: 'SubMenu',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
parentMenu: PropTypes.object,
|
||||
title: PropTypes.any,
|
||||
selectedKeys: PropTypes.array.def([]),
|
||||
openKeys: PropTypes.array.def([]),
|
||||
|
@ -77,6 +76,12 @@ const SubMenu = {
|
|||
},
|
||||
mixins: [BaseMixin],
|
||||
isSubMenu: true,
|
||||
setup() {
|
||||
return { parentMenu: inject('parentMenu', undefined) };
|
||||
},
|
||||
created() {
|
||||
provide('parentMenu', this);
|
||||
},
|
||||
data() {
|
||||
const props = this.$props;
|
||||
const store = props.store;
|
||||
|
@ -127,7 +132,7 @@ const SubMenu = {
|
|||
},
|
||||
methods: {
|
||||
handleUpdated() {
|
||||
const { mode, parentMenu, manualRef } = this.$props;
|
||||
const { mode, parentMenu, manualRef } = this;
|
||||
|
||||
// invoke customized ref to expose component to mixin
|
||||
if (manualRef) {
|
||||
|
@ -196,26 +201,15 @@ const SubMenu = {
|
|||
},
|
||||
|
||||
onMouseLeave(e) {
|
||||
const { eventKey, parentMenu } = this;
|
||||
parentMenu.subMenuInstance = this;
|
||||
// parentMenu.subMenuLeaveFn = () => {
|
||||
// // trigger mouseleave
|
||||
// this.__emit('mouseleave', {
|
||||
// key: eventKey,
|
||||
// domEvent: e,
|
||||
// })
|
||||
// }
|
||||
const { eventKey } = this;
|
||||
this.__emit('mouseleave', {
|
||||
key: eventKey,
|
||||
domEvent: e,
|
||||
});
|
||||
// prevent popup menu and submenu gap
|
||||
// parentMenu.subMenuLeaveTimer = setTimeout(parentMenu.subMenuLeaveFn, 100)
|
||||
},
|
||||
|
||||
onTitleMouseEnter(domEvent) {
|
||||
const { eventKey: key } = this.$props;
|
||||
// this.clearSubMenuTitleLeaveTimer()
|
||||
this.__emit('itemHover', {
|
||||
key,
|
||||
hover: true,
|
||||
|
@ -227,8 +221,7 @@ const SubMenu = {
|
|||
},
|
||||
|
||||
onTitleMouseLeave(e) {
|
||||
const { eventKey, parentMenu } = this;
|
||||
parentMenu.subMenuInstance = this;
|
||||
const { eventKey } = this;
|
||||
this.__emit('itemHover', {
|
||||
key: eventKey,
|
||||
hover: false,
|
||||
|
@ -356,7 +349,6 @@ const SubMenu = {
|
|||
openTransitionName: props.openTransitionName,
|
||||
openAnimation: props.openAnimation,
|
||||
subMenuOpenDelay: props.subMenuOpenDelay,
|
||||
parentMenu: this,
|
||||
subMenuCloseDelay: props.subMenuCloseDelay,
|
||||
forceSubMenuRender: props.forceSubMenuRender,
|
||||
triggerSubMenuAction: props.triggerSubMenuAction,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Comment } from 'vue';
|
||||
import { Comment, inject } from 'vue';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { connect } from '../_util/store';
|
||||
import BaseMixin from '../_util/BaseMixin';
|
||||
|
@ -89,7 +89,6 @@ const SubPopupMenu = {
|
|||
openAnimation: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
openKeys: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])),
|
||||
visible: PropTypes.bool,
|
||||
parentMenu: PropTypes.object,
|
||||
eventKey: PropTypes.string,
|
||||
store: PropTypes.object,
|
||||
|
||||
|
@ -131,6 +130,9 @@ const SubPopupMenu = {
|
|||
),
|
||||
|
||||
mixins: [BaseMixin],
|
||||
setup() {
|
||||
return { parentMenu: inject('parentMenu', undefined) };
|
||||
},
|
||||
created() {
|
||||
const props = getOptionProps(this);
|
||||
this.prevProps = { ...props };
|
||||
|
@ -293,7 +295,6 @@ const SubPopupMenu = {
|
|||
renderMenuItem: this.renderMenuItem,
|
||||
rootPrefixCls: props.prefixCls,
|
||||
index: i,
|
||||
parentMenu: props.parentMenu,
|
||||
// customized ref function, need to be invoked manually in child's componentDidMount
|
||||
manualRef: childProps.disabled ? noop : saveRef.bind(this, key),
|
||||
eventKey: key,
|
||||
|
|
|
@ -74,7 +74,6 @@ export const menuAllProps = [
|
|||
'defaultActiveFirst',
|
||||
'prefixCls',
|
||||
'inlineIndent',
|
||||
'parentMenu',
|
||||
'title',
|
||||
'rootPrefixCls',
|
||||
'eventKey',
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import demo from '../antdv-demo/docs/drawer/demo/index';
|
||||
import demo from '../antdv-demo/docs/dropdown/demo/index';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
Loading…
Reference in New Issue