Vben
2021-03-27 bb67692cfdd5089f0f1d60d4a36b52592db22dde
fix(menu): ensure the menu is activated correctly,fix #432
12个文件已修改
100 ■■■■■ 已修改文件
package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleMenu/src/SimpleMenu.vue 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleMenu/src/SimpleMenuTag.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleMenu/src/components/Menu.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleMenu/src/components/MenuCollapseTransition.vue 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleMenu/src/components/SubMenuItem.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleMenu/src/components/useMenu.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleMenu/src/useOpenKeys.ts 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layouts/default/menu/index.vue 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layouts/default/menu/useLayoutMenu.ts 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
types/global.d.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yarn.lock 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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",
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,
@@ -89,6 +89,14 @@
          }
        },
        { immediate: true }
      );
      watch(
        () => props.items,
        () => {
          setOpenKeys(currentRoute.value.path);
        },
        { flush: 'post' }
      );
      listenerRouteChange((route) => {
@@ -112,7 +120,6 @@
        menuState.activeName = path;
        setOpenKeys(path);
        // if (unref(currentActiveMenu)) return;
      }
      async function handleSelect(key: string) {
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';
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';
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;
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: {
src/components/SimpleMenu/src/components/useMenu.ts
@@ -51,7 +51,7 @@
        uidList: [],
        list: [],
      };
    const ret = [];
    const ret: any[] = [];
    while (parent && parent.type.name !== 'Menu') {
      if (parent.type.name === 'SubMenu') {
        ret.push(parent);
src/components/SimpleMenu/src/useOpenKeys.ts
@@ -8,6 +8,7 @@
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 @@
  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 @@
        }
        menuState.activeSubMenuNames = menuState.openNames;
      },
      16,
      30,
      native
    );
  }
@@ -47,5 +46,5 @@
    return unref(collapse) ? [] : menuState.openNames;
  });
  return { setOpenKeys, getOpenKeys };
  return { setOpenKeys: debounceSetOpenKeys, getOpenKeys };
}
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}
          />
        );
      }
src/layouts/default/menu/useLayoutMenu.ts
@@ -65,10 +65,13 @@
  );
  // 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) {
types/global.d.ts
@@ -3,13 +3,18 @@
  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];
  };
yarn.lock
@@ -2284,10 +2284,10 @@
  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"