Skip to content

路由

项目路由配置存放于 src/router/routes 下面。 src/router/routes/modules用于存放路由模块,在该目录下的文件会自动注册。

配置

模块说明

在 src/router/routes/modules 内的 .js 文件会被视为一个路由模块。

一个路由模块包含以下结构

import { t } from '@/hooks/gui/useI18n';
export default {
path: '/capitalList',
redirect: '/capitalList/capital',
component: () => import('@/views/layout/default/index.vue'),
meta: {
title: t('routes.capitalList.capitalList'),
role: 'apms:capital',
icon: 'capital',
sort: 1,
},
children: [
{
path: 'capital',
name: 'capital',
component: () => import('@/views/capitalList/capital/index.vue'),
meta: {
title: t('routes.capitalList.program'),
role: 'apms:capital:program',
},
},
],
};

多级路由

示例

import { t } from '/@/hooks/web/useI18n';
export default {
path: '/overview',
redirect: '/overview/statistics',
component: () => import('@/views/layout/default/index.vue'),
meta: {
title: '数据概览',
role: 'apms:overview',
icon: 'icon-backlog',
sort: 1,
},
children: [
{
path: '/statistics',
name: 'statistics',
component: () => import('@/views/overview/statistics/index.vue'),
meta: {
title: '数据统计',
role: 'apms:overview:statistics',
},
children: [
{
path: 'statistics2',
name: 'statistics2',
component: () => import('@/views/overview/statistics/index.vue'),
meta: {
title: '数据统计',
role: 'apms:overview:statistics',
},
},
],
},
],
};

Meta 配置说明

export interface RouteMeta {
//菜单排序
sort?: number;
// 路由title 一般必填
title: string;
// 动态路由可打开Tab页数
dynamicLevel?: number;
// 动态路由的实际Path, 即去除路由的动态部分;
realPath?: string;
// 是否忽略权限,只在权限模式为Role的时候有效
ignoreAuth?: boolean;
// 权限字符
role?: string;
// Whether not to cache
noCache?: boolean;
// 是否固定标签
affix?: boolean;
// 图标,也是菜单图标
icon?: string;
// 内嵌iframe的地址
frameSrc?: string;
// 指定该路由切换的动画名
transitionName?: string;
// 隐藏该路由在面包屑上面的显示
hideBreadcrumb?: boolean;
// 隐藏所有子菜单
hideChildrenInMenu?: boolean;
// 当前激活的菜单。用于配置详情页时左侧激活的菜单路径
currentActiveMenu?: string;
// 当前路由不再标签页显示
hideTab?: boolean;
// 当前路由不再菜单显示
hideMenu?: boolean;
isLink?: boolean;
}

外部页面嵌套

只需要将 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'),
},
}

动态路由 Tab 自动关闭功能

若需要开启该功能,需要在动态路由的meta中设置如下两个参数:

  • dynamicLevel 最大能打开的 Tab 标签页数
  • realPath 动态路由实际路径(考虑到动态路由有时候可能存在 N 层的情况, 例:/:id/:subId/:...), 为了减少计算开销, 使用配置方式事先规定好路由的实际路径(注意: 该参数若不设置,将无法使用该功能)
{
path: 'detail/:id',
name: 'TabDetail',
component: () => import('/@/views/demo/feat/tabs/TabDetail.vue'),
meta: {
currentActiveMenu: '/feat/tabs',
title: t('routes.demo.feat.tabDetail'),
hideMenu: true,
dynamicLevel: 3,
realPath: '/feat/tabs/detail',
},
}

图标

这里的 icon 配置,会同步到 菜单(icon 的值可以查看此处)。

新增路由

如何新增一个路由模块

  1. 在 src/router/routes/modules 内新增一个模块文件。

示例,新增 test.js 文件

import { t } from '/@/hooks/web/useI18n';
export default {
path: '/capitalList',
redirect: '/capitalList/capital',
component: () => import('@/views/layout/default/index.vue'),
meta: {
title: t('routes.capitalList.capital'),
role: 'apms:capital',
icon: 'capital',
sort: 2,
},
children: [
{
path: 'capital',
name: 'capital',
component: () => import('@/views/capitalList/capital/index.vue'),
meta: {
title: t('routes.capitalList.program'),
role: 'apms:capital:program',
},
},
],
};

此时路由已添加完成,不需要手动引入,放在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/redirect/index.vue

import { ExceptionEnum } from '@/constants/exception.constant'
export const REDIRECT_NAME = 'Redirect'
export const RedirectRoute = {
path: '/redirect',
name: 'RedirectTo',
component: () => import('@/views/layout/default/index.vue'),
meta: {
title: REDIRECT_NAME,
hideBreadcrumb: true,
hideMenu: true,
},
children: [
{
path: '/redirect/:path(.*)',
name: REDIRECT_NAME,
component: () => import('@/views/redirect/index.vue'),
meta: {
title: REDIRECT_NAME,
hideBreadcrumb: true,
},
},
],
}

多标签页

标签页使用的是 keep-alive 和 router-view 实现,实现切换 tab 后还能保存切换之前的状态。

如何开启页面缓存

开启缓存有 3 个条件

  1. 在 src/settings/project.setting.js 内将openKeepAlive 设置为 true
  2. 路由设置 name,且不能重复
  3. 路由对应的组件加上 name,与路由设置的 name 保持一致
{
...,
// name
name: 'Login',
// 对应组件组件的name
component: () => import('/@/views/sys/login/index.vue'),
...
},
// /@/views/sys/login/index.vue
export default defineComponent({
// 需要和路由的name一致
name:"Login"
});

如何让某个页面不缓存

在 src/settings/projectSetting.js 内将openKeepAlive 设置为 true时,已打开标签页面暂不支持不缓存

如何更改首页路由

首页路由指的是应用程序中的默认路由,当不输入其他任何路由时,会自动重定向到该路由下,并且该路由在 Tab 上是固定的,即使设置affix: false也不允许关闭

例:首页路由配置的是/dashboard/analysis,那么当直接访问 http://localhost:3100/ 会自动跳转到http://localhost:3100/#/dashboard/analysis 上(用户已登录的情况下)

可以将router.setting.js中的BASE_HOME更改为需要你想设置的首页即可

import { convertRefToReadonly } from '@/utils'
export const pagePresets = convertRefToReadonly({
BASE_LOGIN: '/login',
BASE_HOME: '/homeDemo',
ERROR_PAGE: '/exception',
})

路由如何匹配可重复参数

如果你需要匹配具有多个部分的路由,如 /first/second/third,你应该用 *(0 个或多个)和 +(1 个或多个)将参数标记为可重复:

const routes = [
// /:chapters -> 匹配 /one, /one/two, /one/two/three, 等
{ path: '/:chapters+' },
// /:chapters -> 匹配 /, /one, /one/two, /one/two/three, 等
{ path: '/:chapters*' },
]

在 routes 的 basic.js 中调整最新的匹配规则

export const RedirectRoute = {
path: '/redirect',
name: 'RedirectTo',
...
children: [
{
path: '/redirect/:chapters*',
name: REDIRECT_NAME,
...
},
],
}

这将为你提供一个参数数组,而不是一个字符串,并且在使用命名路由时也需要你传递一个数组:

// 给定 { path: '/:chapters*', name: 'chapters' },
router.resolve({ name: 'chapters', params: { chapters: [] } }).href
// 产生 /
router.resolve({ name: 'chapters', params: { chapters: ['id', 'name'] } }).href
// 产生 /a/b
// 给定 { path: '/:chapters+', name: 'chapters' },
router.resolve({ name: 'chapters', params: { chapters: [] } }).href
// 抛出错误,因为 `chapters` 为空