refactor: menu

feat-new-menu
tanjinzhou 2021-05-20 16:05:24 +08:00
parent 8862f604e2
commit 6bf3d283f6
4 changed files with 111 additions and 45 deletions

View File

@ -14,7 +14,7 @@ export default defineComponent({
}, },
setup(props, { slots }) { setup(props, { slots }) {
const fixedMode: MenuMode = 'inline'; const fixedMode: MenuMode = 'inline';
const { forceSubMenuRender, motion, mode, defaultMotions } = useInjectMenu(); const { motion, mode, defaultMotions } = useInjectMenu();
const sameModeRef = computed(() => mode.value === fixedMode); const sameModeRef = computed(() => mode.value === fixedMode);
const destroy = ref(!sameModeRef.value); const destroy = ref(!sameModeRef.value);

View File

@ -87,8 +87,12 @@ export default defineComponent({
mouseLeaveDelay={subMenuCloseDelay.value} mouseLeaveDelay={subMenuCloseDelay.value}
onPopupVisibleChange={onVisibleChange} onPopupVisibleChange={onVisibleChange}
// forceRender={forceSubMenuRender} // forceRender={forceSubMenuRender}
// popupMotion={mergedMotion} v-slots={{
v-slots={{ popup: slots.popup, default: slots.default }} popup: () => {
return slots.popup?.({ visible: innerVisible.value });
},
default: slots.default,
}}
></Trigger> ></Trigger>
); );
}; };

View File

@ -16,6 +16,7 @@ import useDirectionStyle from './hooks/useDirectionStyle';
import PopupTrigger from './PopupTrigger'; import PopupTrigger from './PopupTrigger';
import SubMenuList from './SubMenuList'; import SubMenuList from './SubMenuList';
import InlineSubMenuList from './InlineSubMenuList'; import InlineSubMenuList from './InlineSubMenuList';
import Transition, { getTransitionProps } from 'ant-design-vue/es/_util/transition';
let indexGuid = 0; let indexGuid = 0;
export default defineComponent({ export default defineComponent({
@ -75,6 +76,8 @@ export default defineComponent({
registerMenuInfo, registerMenuInfo,
unRegisterMenuInfo, unRegisterMenuInfo,
selectedSubMenuEventKeys, selectedSubMenuEventKeys,
motion,
defaultMotions,
} = useInjectMenu(); } = useInjectMenu();
registerMenuInfo(eventKey, menuInfo); registerMenuInfo(eventKey, menuInfo);
@ -227,7 +230,13 @@ export default defineComponent({
if (!overflowDisabled.value) { if (!overflowDisabled.value) {
const triggerMode = triggerModeRef.value; const triggerMode = triggerModeRef.value;
const style = ref({});
const className = ref('');
const mergedMotion = computed(() => {
const m = motion.value || defaultMotions.value?.[mode.value];
const res = typeof m === 'function' ? m(style, className) : m;
return res ? getTransitionProps(res.name) : undefined;
});
titleNode = ( titleNode = (
<PopupTrigger <PopupTrigger
mode={triggerMode} mode={triggerMode}
@ -238,11 +247,13 @@ export default defineComponent({
disabled={mergedDisabled.value} disabled={mergedDisabled.value}
onVisibleChange={onPopupVisibleChange} onVisibleChange={onPopupVisibleChange}
v-slots={{ v-slots={{
popup: () => ( popup: ({ visible }) => (
<MenuContextProvider props={{ mode: triggerModeRef }}> <MenuContextProvider props={{ mode: triggerModeRef }}>
<SubMenuList id={popupId} ref={popupRef}> <Transition {...mergedMotion.value}>
<SubMenuList v-show={visible} id={popupId} ref={popupRef}>
{slots.default?.()} {slots.default?.()}
</SubMenuList> </SubMenuList>
</Transition>
</MenuContextProvider> </MenuContextProvider>
), ),
}} }}

View File

@ -1,49 +1,100 @@
<template> <template>
<a-menu v-model:selectedKeys="current" mode="horizontal"> <div style="width: 256px">
<a-menu-item key="mail"> <a-button type="primary" style="margin-bottom: 16px" @click="toggleCollapsed">
<mail-outlined /> <MenuUnfoldOutlined v-if="collapsed" />
Navigation One <MenuFoldOutlined v-else />
</a-button>
<a-menu
v-model:openKeys="openKeys"
v-model:selectedKeys="selectedKeys"
mode="inline"
theme="dark"
:inline-collapsed="collapsed"
>
<a-menu-item key="1">
<PieChartOutlined />
<span>Option 1</span>
</a-menu-item> </a-menu-item>
<a-menu-item key="app" disabled> <a-menu-item key="2">
<appstore-outlined /> <DesktopOutlined />
Navigation Two <span>Option 2</span>
</a-menu-item> </a-menu-item>
<a-sub-menu> <a-menu-item key="3">
<InboxOutlined />
<span>Option 3</span>
</a-menu-item>
<a-sub-menu key="sub1">
<template #title> <template #title>
<span class="submenu-title-wrapper"> <span>
<setting-outlined /> <MailOutlined />
Navigation Three - Submenu <span>Navigation One</span>
</span> </span>
</template> </template>
<a-menu-item-group title="Item 1"> <a-menu-item key="5">Option 5</a-menu-item>
<a-menu-item key="setting:1">Option 1</a-menu-item> <a-menu-item key="6">Option 6</a-menu-item>
<a-menu-item key="setting:2">Option 2</a-menu-item> <a-menu-item key="7">Option 7</a-menu-item>
</a-menu-item-group> <a-menu-item key="8">Option 8</a-menu-item>
<a-menu-item-group title="Item 2">
<a-menu-item key="setting:3">Option 3</a-menu-item>
<a-menu-item key="setting:4">Option 4</a-menu-item>
</a-menu-item-group>
</a-sub-menu> </a-sub-menu>
<a-menu-item key="alipay"> <a-sub-menu key="sub2">
<a href="https://antdv.com" target="_blank" rel="noopener noreferrer"> <template #title>
Navigation Four - Link <span>
</a> <AppstoreOutlined />
</a-menu-item> <span>Navigation Two</span>
</a-menu> </span>
</template> </template>
<script> <a-menu-item key="9">Option 9</a-menu-item>
import { defineComponent, ref } from 'vue'; <a-menu-item key="10">Option 10</a-menu-item>
import { MailOutlined, AppstoreOutlined, SettingOutlined } from '@ant-design/icons-vue'; <a-sub-menu key="sub3" title="Submenu">
<a-menu-item key="11">Option 11</a-menu-item>
<a-menu-item key="12">Option 12</a-menu-item>
</a-sub-menu>
</a-sub-menu>
</a-menu>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs, watch } from 'vue';
import {
MenuFoldOutlined,
MenuUnfoldOutlined,
PieChartOutlined,
MailOutlined,
DesktopOutlined,
InboxOutlined,
AppstoreOutlined,
} from '@ant-design/icons-vue';
export default defineComponent({ export default defineComponent({
components: { components: {
MenuFoldOutlined,
MenuUnfoldOutlined,
PieChartOutlined,
MailOutlined, MailOutlined,
DesktopOutlined,
InboxOutlined,
AppstoreOutlined, AppstoreOutlined,
SettingOutlined,
}, },
setup() { setup() {
const current = ref(['mail']); const state = reactive({
collapsed: false,
selectedKeys: ['1'],
openKeys: ['sub1'],
preOpenKeys: ['sub1'],
});
watch(
() => state.openKeys,
(val, oldVal) => {
state.preOpenKeys = oldVal;
},
);
const toggleCollapsed = () => {
state.collapsed = !state.collapsed;
state.openKeys = state.collapsed ? [] : state.preOpenKeys;
};
return { return {
current, ...toRefs(state),
toggleCollapsed,
}; };
}, },
}); });