路由
项目路由配置存放于src/router/routes 下面。 src/router/routes/modules用于存放路由模块,在该文件下内的文件会自动注册
vue-ts-vite-admin> yarn add vue-router@next
package.json
"dependencies": {
"vue": "^3.0.5",
"vue-router": "^4.0.10"
},
配置
模块说明
在src/router/routes/modules内的一个.ts
文件会被视为一个路由模块。
router\routes\index.ts import.
一个路由模块包含以下结构
import type { AppRouteModule } from '/@/router/types';
import { LAYOUT } from '/@/router/constant';
import { t } from '/@/hooks/web/useI18n';
const dashboard: AppRouteModule = {
path: '/dashboard',
name: 'Dashboard',
component: LAYOUT,
redirect: '/dashboard/analysis',
meta: {
icon: 'ion:grid-outline',
title: t('routes.dashboard.dashboard'),
},
children: [
{
path: 'analysis',
name: 'Analysis',
component: () => import('/@/views/dashboard/analysis/index.vue'),
meta: {
affix: true,
title: t('routes.dashboard.analysis'),
},
},
{
path: 'workbench',
name: 'Workbench',
component: () => import('/@/views/dashboard/workbench/index.vue'),
meta: {
title: t('routes.dashboard.workbench'),
},
},
],
};
export default dashboard;
多级路由
注意事项
- 整个项目所有路由 name 不能重复
- 所有的多级路由最终都会转成二级路由,所以不能内嵌子路由
- 除了 layout 对应的 path 前面需要加
/
,其余子路由都不要以/
开头
示例
import type { AppRouteModule } from '/@/router/types';
import { getParentLayout, LAYOUT } from '/@/router/constant';
import { t } from '/@/hooks/web/useI18n';
const permission: AppRouteModule = {
path: '/level',
name: 'Level',
component: LAYOUT,
redirect: '/level/menu1/menu1-1/menu1-1-1',
meta: {
icon: 'ion:menu-outline',
title: t('routes.demo.level.level'),
},
children: [
{
path: 'menu1',
name: 'Menu1Demo',
component: getParentLayout('Menu1Demo'),
meta: {
title: 'Menu1',
},
redirect: '/level/menu1/menu1-1/menu1-1-1',
children: [
{
path: 'menu1-1',
name: 'Menu11Demo',
component: getParentLayout('Menu11Demo'),
meta: {
title: 'Menu1-1',
},
redirect: '/level/menu1/menu1-1/menu1-1-1',
children: [
{
path: 'menu1-1-1',
name: 'Menu111Demo',
component: () => import('/@/views/demo/level/Menu111.vue'),
meta: {
title: 'Menu111',
},
},
],
},
],
},
],
};
export default permission;
Meta 配置说明
export interface RouteMeta {
// 路由title 一般必填
title: string;
// 是否忽略权限,只在权限模式为Role的时候有效
ignoreAuth?: boolean;
// 可以访问的角色,只在权限模式为Role的时候有效
roles?: RoleEnum[];
// 是否忽略KeepAlive缓存
ignoreKeepAlive?: boolean;
// 是否固定标签
affix?: boolean;
// 图标,也是菜单图标
icon?: string;
// 内嵌iframe的地址
frameSrc?: string;
// 指定该路由切换的动画名
transitionName?: string;
// 隐藏该路由在面包屑上面的显示
hideBreadcrumb?: boolean;
// 如果该路由会携带参数,且需要在tab页上面显示。则需要设置为true
carryParam?: boolean;
// 隐藏所有子菜单
hideChildrenInMenu?: boolean;
// 当前激活的菜单。用于配置详情页时左侧激活的菜单路径
currentActiveMenu?: string;
// 当前路由不再标签页显示
hideTab?: boolean;
// 当前路由不再菜单显示
hideMenu?: boolean;
// 菜单排序,只对第一级有效
orderNo?: number;
}
外部页面嵌套
只需要将 frameSrc 设置为需要跳转的地址即可
const IFrame = () => import('/@/views/sys/iframe/FrameBlank.vue');
{
path: 'doc',
name: 'Doc',
component: IFrame,
meta: {
frameSrc: 'https://vvbin.cn/doc-next/',
title: t('routes.demo.iframe.doc'),
},
},
外链
只需要将 path 设置为需要跳转的HTTP 地址即可
{
path: 'https://vvbin.cn/doc-next/',
name: 'DocExternal',
component: IFrame,
meta: {
title: t('routes.demo.iframe.docExternal'),
},
}
图标
这里的 icon 配置,会同步到 菜单
icon 的值可以查看 Icon
新增路由
如何新增一个路由模块
- 在src/router/routes/modules内新增一个模块文件
示例,在src/router/routes/modules下新增 test.ts 文件
import type { AppRouteModule } from '/@/router/types';
import { LAYOUT } from '/@/router/constant';
import { t } from '/@/hooks/web/useI18n';
const dashboard: AppRouteModule = {
path: '/about',
name: 'About',
component: LAYOUT,
redirect: '/about/index',
meta: {
icon: 'simple-icons:about-dot-me',
title: t('routes.dashboard.about'),
},
children: [
{
path: 'index',
name: 'AboutPage',
component: () => import('/@/views/sys/about/index.vue'),
meta: {
title: t('routes.dashboard.about'),
icon: 'simple-icons:about-dot-me',
},
},
],
};
export default dashboard;
到这里你路由已经添加完成,不需要手动引入,放在src/router/routes/modules内的文件会自动被加载
验证
您可以尝试访问 ip:端口/about/index出现对应组件内容即代表成功
路由刷新
项目中采用的是重定向方式
实现
import { useRedo } from '/@/hooks/web/usePage';
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const redo = useRedo();
// 执行刷新
redo();
return {};
},
});
Redirect
src/views/sys/redirect/index.vue
import { defineComponent, unref } from 'vue';
import { useRouter } from 'vue-router';
export default defineComponent({
name: 'Redirect',
setup() {
const { currentRoute, replace } = useRouter();
const { params, query } = unref(currentRoute);
const { path } = params;
const _path = Array.isArray(path) ? path.join('/') : path;
replace({
path: '/' + _path,
query,
});
return {};
},
});
页面跳转
页面跳转建议采用项目提供的 useGo
方式
import { useGo } from '/@/hooks/web/usePage';
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const go = useGo();
// 执行刷新
go();
go(PageEnum.Home);
return {};
},
});
多标签页
标签页使用的是 keep-alive
和 router-view
实现,实现切换 tab 后还能保存切换之前的状态。
如何开启页面缓存
开启缓存有 3 个条件
- 在src/settings/projectSetting.ts内将
openKeepAlive
设置为true
- 路由设置 name,且不能重复
- 路由对应的组件加上 name,与路由设置的 name 保持一致
{
...,
// name
name: 'Login',
// 对应组件组件的name
component: () => import('/@/views/sys/login/index.vue'),
...
},
// /@/views/sys/login/index.vue
export default defineComponent({
// 需要和路由的name一致
name:"Login"
});
注意
keep-alive 生效的前提是
include - 字符串或正则表达式,只有名称匹配的组件会被缓存
所以需要将路由的 name 属性及对应的页面的 name 设置成一样
如何让某个页面不缓存
可在 router.meta 下配置
可以将 ignoreKeepAlive
配置成true
即可关闭缓存。
export interface RouteMeta {
// 是否忽略KeepAlive缓存
ignoreKeepAlive?: boolean;
}