Procházet zdrojové kódy

fix(menu): ensure the menu is activated correctly,fix #432

Vben před 4 roky
rodič
revize
bb67692cfd

+ 1 - 1
package.json

@@ -34,7 +34,7 @@
     "@iconify/iconify": "^2.0.0-rc.6",
     "@vueuse/core": "^4.6.2",
     "@zxcvbn-ts/core": "^0.3.0",
-    "ant-design-vue": "2.1.0",
+    "ant-design-vue": "2.1.1",
     "apexcharts": "^3.26.0",
     "axios": "^0.21.1",
     "crypto-js": "^4.0.0",

+ 9 - 2
src/components/SimpleMenu/src/SimpleMenu.vue

@@ -18,7 +18,6 @@
   </Menu>
 </template>
 <script lang="ts">
-  import type { PropType } from 'vue';
   import type { MenuState } from './types';
   import type { Menu as MenuType } from '/@/router/types';
 
@@ -69,6 +68,7 @@
       const { currentRoute } = useRouter();
       const { prefixCls } = useDesign('simple-menu');
       const { items, accordion, mixSider, collapse } = toRefs(props);
+
       const { setOpenKeys, getOpenKeys } = useOpenKeys(
         menuState,
         items,
@@ -91,6 +91,14 @@
         { immediate: true }
       );
 
+      watch(
+        () => props.items,
+        () => {
+          setOpenKeys(currentRoute.value.path);
+        },
+        { flush: 'post' }
+      );
+
       listenerRouteChange((route) => {
         if (route.name === REDIRECT_NAME) return;
 
@@ -112,7 +120,6 @@
         menuState.activeName = path;
 
         setOpenKeys(path);
-        // if (unref(currentActiveMenu)) return;
       }
 
       async function handleSelect(key: string) {

+ 0 - 1
src/components/SimpleMenu/src/SimpleMenuTag.vue

@@ -3,7 +3,6 @@
 </template>
 <script lang="ts">
   import type { Menu } from '/@/router/types';
-  import type { PropType } from 'vue';
 
   import { defineComponent, computed } from 'vue';
 

+ 1 - 0
src/components/SimpleMenu/src/components/Menu.vue

@@ -18,6 +18,7 @@
     getCurrentInstance,
     provide,
   } from 'vue';
+
   import { useDesign } from '/@/hooks/web/useDesign';
   import { propTypes } from '/@/utils/propTypes';
   import { createSimpleRootMenuContext } from './useSimpleMenuContext';

+ 6 - 6
src/components/SimpleMenu/src/components/MenuCollapseTransition.vue

@@ -12,7 +12,7 @@
     setup() {
       return {
         on: {
-          beforeEnter(el: any) {
+          beforeEnter(el) {
             addClass(el, 'collapse-transition');
             if (!el.dataset) el.dataset = {};
 
@@ -24,7 +24,7 @@
             el.style.paddingBottom = 0;
           },
 
-          enter(el: any) {
+          enter(el) {
             el.dataset.oldOverflow = el.style.overflow;
             if (el.scrollHeight !== 0) {
               el.style.height = el.scrollHeight + 'px';
@@ -39,13 +39,13 @@
             el.style.overflow = 'hidden';
           },
 
-          afterEnter(el: any) {
+          afterEnter(el) {
             removeClass(el, 'collapse-transition');
             el.style.height = '';
             el.style.overflow = el.dataset.oldOverflow;
           },
 
-          beforeLeave(el: any) {
+          beforeLeave(el) {
             if (!el.dataset) el.dataset = {};
             el.dataset.oldPaddingTop = el.style.paddingTop;
             el.dataset.oldPaddingBottom = el.style.paddingBottom;
@@ -55,7 +55,7 @@
             el.style.overflow = 'hidden';
           },
 
-          leave(el: any) {
+          leave(el) {
             if (el.scrollHeight !== 0) {
               addClass(el, 'collapse-transition');
               el.style.height = 0;
@@ -64,7 +64,7 @@
             }
           },
 
-          afterLeave(el: any) {
+          afterLeave(el) {
             removeClass(el, 'collapse-transition');
             el.style.height = '';
             el.style.overflow = el.dataset.oldOverflow;

+ 1 - 1
src/components/SimpleMenu/src/components/SubMenuItem.vue

@@ -78,7 +78,7 @@
   import { isBoolean, isObject } from '/@/utils/is';
   import Mitt from '/@/utils/mitt';
 
-  const DELAY = 200;
+  const DELAY = 250;
   export default defineComponent({
     name: 'SubMenu',
     components: {

+ 1 - 1
src/components/SimpleMenu/src/components/useMenu.ts

@@ -51,7 +51,7 @@ export function useMenuItem(instance: ComponentInternalInstance | null) {
         uidList: [],
         list: [],
       };
-    const ret = [];
+    const ret: any[] = [];
     while (parent && parent.type.name !== 'Menu') {
       if (parent.type.name === 'SubMenu') {
         ret.push(parent);

+ 6 - 7
src/components/SimpleMenu/src/useOpenKeys.ts

@@ -8,6 +8,7 @@ import { uniq } from 'lodash-es';
 import { getAllParentPath } from '/@/router/helper/menuHelper';
 
 import { useTimeoutFn } from '/@/hooks/core/useTimeout';
+import { useDebounce } from '../../../hooks/core/useDebounce';
 
 export function useOpenKeys(
   menuState: MenuState,
@@ -15,22 +16,20 @@ export function useOpenKeys(
   accordion: Ref<boolean>,
   mixSider: Ref<boolean>,
   collapse: Ref<boolean>
-  // mode: Ref<MenuModeEnum>,
 ) {
+  const [debounceSetOpenKeys] = useDebounce(setOpenKeys, 50);
   async function setOpenKeys(path: string) {
-    // if (mode.value === MenuModeEnum.HORIZONTAL) {
-    //   return;
-    // }
     const native = !mixSider.value;
+    const menuList = toRaw(menus.value);
     useTimeoutFn(
       () => {
-        const menuList = toRaw(menus.value);
         if (menuList?.length === 0) {
           menuState.activeSubMenuNames = [];
           menuState.openNames = [];
           return;
         }
         const keys = getAllParentPath(menuList, path);
+
         if (!unref(accordion)) {
           menuState.openNames = uniq([...menuState.openNames, ...keys]);
         } else {
@@ -38,7 +37,7 @@ export function useOpenKeys(
         }
         menuState.activeSubMenuNames = menuState.openNames;
       },
-      16,
+      30,
       native
     );
   }
@@ -47,5 +46,5 @@ export function useOpenKeys(
     return unref(collapse) ? [] : menuState.openNames;
   });
 
-  return { setOpenKeys, getOpenKeys };
+  return { setOpenKeys: debounceSetOpenKeys, getOpenKeys };
 }

+ 17 - 15
src/layouts/default/menu/index.vue

@@ -92,6 +92,20 @@
           },
         ];
       });
+
+      const getCommonProps = computed(() => {
+        const menus = unref(menusRef);
+        return {
+          menus,
+          beforeClickFn: beforeMenuClickFn,
+          items: menus,
+          theme: unref(getComputedMenuTheme),
+          accordion: unref(getAccordion),
+          collapse: unref(getCollapsed),
+          collapsedShowTitle: unref(getCollapsedShowTitle),
+          onMenuClick: handleMenuClick,
+        };
+      });
       /**
        * click menu
        * @param menu
@@ -126,31 +140,19 @@
       }
 
       function renderMenu() {
-        const menus = unref(menusRef);
+        const { menus, ...menuProps } = unref(getCommonProps);
         // console.log(menus);
         if (!menus || !menus.length) return null;
         return !props.isHorizontal ? (
-          <SimpleMenu
-            beforeClickFn={beforeMenuClickFn}
-            items={menus}
-            theme={unref(getComputedMenuTheme)}
-            accordion={unref(getAccordion)}
-            collapse={unref(getCollapsed)}
-            collapsedShowTitle={unref(getCollapsedShowTitle)}
-            onMenuClick={handleMenuClick}
-          />
+          <SimpleMenu {...menuProps} items={menus} />
         ) : (
           <BasicMenu
-            beforeClickFn={beforeMenuClickFn}
+            {...menuProps}
             isHorizontal={props.isHorizontal}
             type={unref(getMenuType)}
-            collapsedShowTitle={unref(getCollapsedShowTitle)}
             showLogo={unref(getIsShowLogo)}
             mode={unref(getComputedMenuMode)}
-            theme={unref(getComputedMenuTheme)}
             items={menus}
-            accordion={unref(getAccordion)}
-            onMenuClick={handleMenuClick}
           />
         );
       }

+ 7 - 4
src/layouts/default/menu/useLayoutMenu.ts

@@ -65,10 +65,13 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
   );
 
   // split Menu changes
-  watch([() => getSplit.value], () => {
-    if (unref(splitNotLeft)) return;
-    genMenus();
-  });
+  watch(
+    () => getSplit.value,
+    () => {
+      if (unref(splitNotLeft)) return;
+      genMenus();
+    }
+  );
 
   // Handle left menu split
   async function handleSplitLeftMenu(parentPath: string) {

+ 5 - 0
types/global.d.ts

@@ -3,13 +3,18 @@ import type {
   VNode,
   ComponentPublicInstance,
   FunctionalComponent,
+  PropType as VuePropType,
 } from 'vue';
+
 declare global {
   // declare interface Window {
   // Global vue app instance
   //   __APP__: App<Element>;
   // }
 
+  // vue
+  declare type PropType<T> = VuePropType<T>;
+
   export type Writable<T> = {
     -readonly [P in keyof T]: T[P];
   };

+ 4 - 4
yarn.lock

@@ -2284,10 +2284,10 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
   dependencies:
     color-convert "^2.0.1"
 
-ant-design-vue@2.1.0:
-  version "2.1.0"
-  resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-2.1.0.tgz#2489240f638f39874281e237544b857ebce52d18"
-  integrity sha512-wzgwHRuwZrSvixccNlvas2gTWBkmfMrifbSsP+ga8VV6F0C6DdlimeFo+P99AxnVgpNVk8OUq9RVDQjb1UGk6g==
+ant-design-vue@2.1.1:
+  version "2.1.1"
+  resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-2.1.1.tgz#5c2f3d86177e197f6dbb167f691a9d10104e61c3"
+  integrity sha512-ohTEIBFRkODRTFXRHeizL/uKNOZY5+4r2y/GXiKEdvrxiTRgHgDNMWKsncG/+G6MXxOIe2Reg+r8jHS8nGDqtQ==
   dependencies:
     "@ant-design-vue/use" "^0.0.1-0"
     "@ant-design/icons-vue" "^6.0.0"