Skip to content

Commit 34f2906

Browse files
committed
使用 useId 优化菜单逻辑
1 parent ab97197 commit 34f2906

File tree

3 files changed

+20
-7
lines changed

3 files changed

+20
-7
lines changed

src/layouts/components/Menu/index.vue

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ const props = withDefaults(
2020
},
2121
)
2222
23+
// 用于缓存对象到 ID 的映射
24+
const idMap = new WeakMap<object, string>()
25+
// 获取对象的唯一 ID,如果已存在则返回缓存的 ID,否则生成新的
26+
function getUseId(obj: object): string {
27+
if (!idMap.has(obj)) {
28+
idMap.set(obj, useId())
29+
}
30+
return idMap.get(obj)!
31+
}
32+
2333
const activeIndex = ref<MenuInjection['activeIndex']>(props.value)
2434
const items = ref<MenuInjection['items']>({})
2535
const subMenus = ref<MenuInjection['subMenus']>({})
@@ -32,7 +42,7 @@ const isMenuPopup = computed<MenuInjection['isMenuPopup']>(() => {
3242
// 解析传入的 menu 数据,并保存到 items 和 subMenus 对象中
3343
function initItems(menu: MenuProps['menu'], parentPaths: string[] = []) {
3444
menu.forEach((item) => {
35-
const index = item.path ?? JSON.stringify(item)
45+
const index = item.path ?? getUseId(item)
3646
if (item.children) {
3747
const indexPath = [...parentPaths, index]
3848
subMenus.value[index] = {
@@ -144,6 +154,7 @@ watch(() => props.collapse, (value) => {
144154
145155
provide(rootMenuInjectionKey, reactive({
146156
props,
157+
getUseId,
147158
items,
148159
subMenus,
149160
activeIndex,
@@ -164,10 +175,10 @@ provide(rootMenuInjectionKey, reactive({
164175
'py-1': props.mode === 'vertical',
165176
})"
166177
>
167-
<template v-for="item in menu" :key="item.path ?? JSON.stringify(item)">
178+
<template v-for="item in menu" :key="item.path ?? getUseId(item)">
168179
<template v-if="item.meta?.menu !== false">
169-
<SubMenu v-if="item.children?.length" :menu="item" :unique-key="[item.path ?? JSON.stringify(item)]" />
170-
<Item v-else :item="item" :unique-key="[item.path ?? JSON.stringify(item)]" @click="handleMenuItemClick(item.path ?? JSON.stringify(item))" />
180+
<SubMenu v-if="item.children?.length" :menu="item" :unique-key="[item.path ?? getUseId(item)]" />
181+
<Item v-else :item="item" :unique-key="[item.path ?? getUseId(item)]" @click="handleMenuItemClick(item.path ?? getUseId(item))" />
171182
</template>
172183
</template>
173184
</div>

src/layouts/components/Menu/sub.vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ const props = withDefaults(
1616
},
1717
)
1818
19-
const index = props.menu.path ?? JSON.stringify(props.menu)
2019
const itemRef = useTemplateRef('itemRef')
2120
const subMenuRef = useTemplateRef('subMenuRef')
2221
const rootMenu = inject(rootMenuInjectionKey)!
2322
23+
const index = props.menu.path ?? rootMenu.getUseId(props.menu)
24+
2425
const opened = computed(() => {
2526
return rootMenu.openedMenus.includes(props.uniqueKey.at(-1)!)
2627
})
@@ -201,8 +202,8 @@ function handleMouseleave() {
201202
'py-1': rootMenu.isMenuPopup,
202203
})"
203204
>
204-
<template v-for="item in menu.children" :key="item.path ?? JSON.stringify(item)">
205-
<SubMenu v-if="item.meta?.menu !== false" :unique-key="[...uniqueKey, item.path ?? JSON.stringify(item)]" :menu="item" :level="level + 1" />
205+
<template v-for="item in menu.children" :key="item.path ?? rootMenu.getUseId(item)">
206+
<SubMenu v-if="item.meta?.menu !== false" :unique-key="[...uniqueKey, item.path ?? rootMenu.getUseId(item)]" :menu="item" :level="level + 1" />
206207
</template>
207208
</FaScrollArea>
208209
</Transition>

src/layouts/components/Menu/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface MenuProps {
1818

1919
export interface MenuInjection {
2020
props: MenuProps
21+
getUseId: (obj: object) => string
2122
items: Record<string, MenuItem>
2223
subMenus: Record<string, MenuItem>
2324
activeIndex: MenuProps['value']

0 commit comments

Comments
 (0)