<template>
<div class="sidebar">
<div>{{ t('menu.dashboard') }}</div>
<n-scrollbar>
<n-menu :options="menuOptions" />
</n-scrollbar>
</div>
</template>
<script lang="ts" setup>
import { h, Component, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { RouteRecordRaw, RouterLink } from 'vue-router'
import { useRouter } from 'vue-router'
import { computed } from 'vue'
import { useAppStore } from '@/store'
import type { MenuOption } from 'naive-ui'
import { NIcon } from 'naive-ui'
import { DashboardOutlined as DashboardIcon } from '@vicons/antd'
const router = useRouter()
const { t, locale } = useI18n()
console.log(router.getRoutes())
const appStore = useAppStore()
const routers = computed(() => {
return appStore.routers.filter(value => !value.meta?.hidden)
})
const menuOptions = ref<MenuOption[]>([])
const iconMap: { [index: string]: any } = {
Dashboard: DashboardIcon
}
function renderIcon(icon: Component) {
return () => h(NIcon, null, { default: () => h(icon) })
}
const genMenu = () => {
menuOptions.value = []
for (const item of routers.value) {
const children = []
for (const item2 of item?.children || []) {
children.push({
label: () =>
h(
RouterLink,
{
to: {
name: item2.name
}
},
{ default: () => t(item2.meta?.locale as string) }
),
key: item2.name as string
})
}
const menu: MenuOption = {
key: item.name as string,
label: t(item.meta?.locale as string),
icon: renderIcon(iconMap[item.name as string]),
children
}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
menuOptions.value.push(menu)
}
}
genMenu()
watch(
() => locale.value,
() => {
genMenu()
}
)
</script>
vue-router 的类型 RouteRecordRaw, 一个属性有好几种类型, 然后用起来 ts 总是报类型不匹配, 用了大量 as string 来解决报错, 好难受, 我之前都是写 js, 可能对 ts 理解有误, 怎么才能优雅的使用, 有个报错说我嵌套太深, 还不得不用 // @ts-ignore 来解决
1
gogogo2000 2022-12-16 12:17:47 +08:00
vue 对 ts 的兼容性一向来都不太好,这也是 react 的重大优势之一,有时候没办法只能 as any……
|
2
wunonglin 2022-12-16 12:39:39 +08:00
你 routers 的类型推断出来了吗?还是什么问题单单代码看不出,你去 stackblitz.com 写个例子。
|
3
xpyusrs OP @gogogo2000 用 react 就没有这个问题了嘛? 如果这样的话我可以转 react
|
5
anguiao 2022-12-16 13:38:17 +08:00
路由的元信息是可以预先声明的呀,文档里面有写。
https://router.vuejs.org/zh/guide/advanced/meta.html#typescript |
6
chengxy 2022-12-16 13:42:21 +08:00
你用法不对,你的 routers 类型应该和 MenuOption 类型对上的,RouteRecordRaw 里面的参数你可以使用重写功能去重写。
|
7
chengxy 2022-12-16 13:47:28 +08:00
@gogogo2000 #1 都 24 年了,现在完全不是问题了
|
11
ccyu220 2022-12-16 15:32:25 +08:00
我建议 menu 这种,你直接换成 tsx 来写。
|
12
wunonglin 2022-12-16 17:40:40 +08:00
@xpyusrs #4
噢噢。router meta 这个问题在 vue2 时代也是这样,只能类型覆盖。 虽然但是,不建议直接把路由当做 navmenu 以及把路由表引到 ui 层使用,路由归路由,menu 归 menu 。这是个很标准的错误用法,虽然可以这么用,但是建议不。 |
13
Bingchunmoli 2022-12-16 20:25:54 +08:00 via Android
没有 vue3 的一些代码示例,,pinia 什么的 ts 都不太会用
|