feat: add menu template support

pull/3053/head
tangjinzhou 2020-10-20 23:13:49 +08:00
parent a16ca20770
commit f10d0f1e4d
6 changed files with 51 additions and 19 deletions

@ -1 +1 @@
Subproject commit b35f6ab6b59169fa7c0413263f75c185bd62b97c Subproject commit ab46da93f0bca77a66a25f0ef427fa106d6dff13

View File

@ -8,7 +8,7 @@ function getDisplayName(WrappedComponent) {
} }
const defaultMapStateToProps = () => ({}); const defaultMapStateToProps = () => ({});
export default function connect(mapStateToProps) { export default function connect(mapStateToProps, injectExtraPropsKey) {
const shouldSubscribe = !!mapStateToProps; const shouldSubscribe = !!mapStateToProps;
const finalMapStateToProps = mapStateToProps || defaultMapStateToProps; const finalMapStateToProps = mapStateToProps || defaultMapStateToProps;
return function wrapWithConnect(WrappedComponent) { return function wrapWithConnect(WrappedComponent) {
@ -24,18 +24,25 @@ export default function connect(mapStateToProps) {
setup() { setup() {
return { return {
storeContext: inject('storeContext', {}), storeContext: inject('storeContext', {}),
injectExtraProps: injectExtraPropsKey ? inject(injectExtraPropsKey, () => ({})) : {},
}; };
}, },
data() { data() {
this.store = this.storeContext.store; this.store = this.storeContext.store;
this.preProps = getOptionProps(this); this.preProps = { ...getOptionProps(this), ...this.injectExtraProps };
watchEffect(() => { watchEffect(() => {
if (mapStateToProps && mapStateToProps.length === 2) { if (mapStateToProps && mapStateToProps.length === 2) {
this.subscribed = finalMapStateToProps(this.store.getState(), this.$props); this.subscribed = finalMapStateToProps(this.store.getState(), {
...this.$props,
...this.injectExtraProps,
});
} }
}); });
return { return {
subscribed: finalMapStateToProps(this.store.getState(), this.$props), subscribed: finalMapStateToProps(this.store.getState(), {
...this.$props,
...this.injectExtraProps,
}),
}; };
}, },
mounted() { mounted() {
@ -50,7 +57,7 @@ export default function connect(mapStateToProps) {
if (!this.unsubscribe) { if (!this.unsubscribe) {
return; return;
} }
const props = getOptionProps(this); const props = { ...getOptionProps(this), ...this.injectExtraProps };
const nextSubscribed = finalMapStateToProps(this.store.getState(), props); const nextSubscribed = finalMapStateToProps(this.store.getState(), props);
if ( if (
!shallowEqual(this.preProps, props) || !shallowEqual(this.preProps, props) ||
@ -79,12 +86,12 @@ export default function connect(mapStateToProps) {
}, },
render() { render() {
const { $slots = {}, subscribed, store, $attrs } = this; const { $slots = {}, subscribed, store, $attrs } = this;
const props = getOptionProps(this); const props = { ...getOptionProps(this), ...this.injectExtraProps };
this.preProps = { ...props }; this.preProps = { ...props };
const wrapProps = { const wrapProps = {
...$attrs,
...props, ...props,
...subscribed, ...subscribed,
...$attrs,
store, store,
ref: 'wrappedInstance', ref: 'wrappedInstance',
}; };

View File

@ -0,0 +1,17 @@
import PropTypes from '../_util/vue-types';
import { provide, reactive } from 'vue';
const FunctionProvider = {
inheritAttrs: false,
props: {
injectExtraPropsKey: PropTypes.string,
},
setup(props, { slots, attrs }) {
if (props.injectExtraPropsKey) {
provide(props.injectExtraPropsKey, reactive(attrs));
}
return () => slots.default && slots.default();
},
};
export default FunctionProvider;

View File

@ -6,7 +6,7 @@ import { connect } from '../_util/store';
import { noop, menuAllProps } from './util'; import { noop, menuAllProps } from './util';
import { getComponent, getSlot, findDOMNode } from '../_util/props-util'; import { getComponent, getSlot, findDOMNode } from '../_util/props-util';
import { inject } from 'vue'; import { inject } from 'vue';
const injectExtraPropsKey = 'ANT_MENU_PROVIDER_PROPS_KEY';
const props = { const props = {
attribute: PropTypes.object, attribute: PropTypes.object,
rootPrefixCls: PropTypes.string, rootPrefixCls: PropTypes.string,
@ -199,10 +199,13 @@ const MenuItem = {
}, },
}; };
const connected = connect(({ activeKey, selectedKeys }, { eventKey, subMenuKey }) => ({ const connected = connect(
active: activeKey[subMenuKey] === eventKey, ({ activeKey, selectedKeys }, { eventKey, subMenuKey }) => ({
isSelected: selectedKeys.indexOf(eventKey) !== -1, active: activeKey[subMenuKey] === eventKey,
}))(MenuItem); isSelected: selectedKeys.indexOf(eventKey) !== -1,
}),
injectExtraPropsKey,
)(MenuItem);
export default connected; export default connected;
export { props as menuItemProps }; export { props as menuItemProps };

View File

@ -13,7 +13,7 @@ import { noop, loopMenuItemRecursively, getMenuIdFromSubMenuEventKey } from './u
import getTransitionProps from '../_util/getTransitionProps'; import getTransitionProps from '../_util/getTransitionProps';
let guid = 0; let guid = 0;
const injectExtraPropsKey = 'ANT_MENU_PROVIDER_PROPS_KEY';
const popupPlacementMap = { const popupPlacementMap = {
horizontal: 'bottomLeft', horizontal: 'bottomLeft',
vertical: 'rightTop', vertical: 'rightTop',
@ -337,6 +337,7 @@ const SubMenu = {
}, },
renderChildren(children) { renderChildren(children) {
const props = { ...this.$props, ...this.$attrs }; const props = { ...this.$props, ...this.$attrs };
const subPopupMenuProps = { const subPopupMenuProps = {
mode: props.mode === 'horizontal' ? 'vertical' : props.mode, mode: props.mode === 'horizontal' ? 'vertical' : props.mode,
visible: props.isOpen, visible: props.isOpen,
@ -541,7 +542,7 @@ const connected = connect(({ openKeys, activeKey, selectedKeys }, { eventKey, su
active: activeKey[subMenuKey] === eventKey, active: activeKey[subMenuKey] === eventKey,
selectedKeys, selectedKeys,
}; };
})(SubMenu); }, injectExtraPropsKey)(SubMenu);
connected.isSubMenu = true; connected.isSubMenu = true;

View File

@ -6,7 +6,6 @@ import KeyCode from '../_util/KeyCode';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import { getKeyFromChildrenIndex, loopMenuItem, noop, isMobileDevice, menuAllProps } from './util'; import { getKeyFromChildrenIndex, loopMenuItem, noop, isMobileDevice, menuAllProps } from './util';
import DOMWrap from './DOMWrap'; import DOMWrap from './DOMWrap';
import { cloneElement } from '../_util/vnode';
import { import {
initDefaultProps, initDefaultProps,
getOptionProps, getOptionProps,
@ -14,7 +13,8 @@ import {
splitAttrs, splitAttrs,
getPropsData, getPropsData,
} from '../_util/props-util'; } from '../_util/props-util';
import FunctionProvider from './FunctionProvider';
const injectExtraPropsKey = 'ANT_MENU_PROVIDER_PROPS_KEY';
function allDisabled(arr) { function allDisabled(arr) {
if (!arr.length) { if (!arr.length) {
return true; return true;
@ -323,7 +323,11 @@ const SubPopupMenu = {
if (props.mode === 'inline' || isMobileDevice()) { if (props.mode === 'inline' || isMobileDevice()) {
newChildProps.triggerSubMenuAction = 'click'; newChildProps.triggerSubMenuAction = 'click';
} }
return cloneElement(child, newChildProps); return (
<FunctionProvider injectExtraPropsKey={injectExtraPropsKey} {...newChildProps}>
{child}
</FunctionProvider>
);
}, },
renderMenuItem(c, i, subMenuKey) { renderMenuItem(c, i, subMenuKey) {
@ -389,4 +393,4 @@ const SubPopupMenu = {
}, },
}; };
export default connect()(SubPopupMenu); export default connect(undefined)(SubPopupMenu);