了解一下前端路由 常用信息配置:
注意事项
示例
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: 'tabs/:id', name: 'TabsParams', component: getParentLayout('TabsParams'), meta: { carryParam: true, hidePathForChildren: true, // 本级path将会在子级菜单中合成完整path时会忽略这一层级 }, children: [ path: 'tabs/id1', // 其上级有标记hidePathForChildren,所以本级在生成菜单时最终的path为 /level/tabs/id1 name: 'TabsParams', component: getParentLayout('TabsParams'), meta: { carryParam: true, ignoreRoute: true, // 本路由仅用于菜单生成,不会在实际的路由表中出现 }, ] }, { 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;
export interface RouteMeta {// 路由title 一般必填title: string;// 动态路由可打开Tab页数dynamicLevel?: number;// 动态路由的实际Path, 即去除路由的动态部分;realPath?: string;// 是否忽略权限,只在权限模式为Role的时候有效ignoreAuth?: boolean;// 可以访问的角色,只在权限模式为Role的时候有效roles?: RoleEnum[];// 是否忽略KeepAlive缓存ignoreKeepAlive?: boolean;// 是否固定标签affix?: boolean;// 图标,也是菜单图标icon?: string;// 内嵌iframe的地址frameSrc?: string;// 指定该路由切换的动画名transitionName?: string;// 隐藏该路由在面包屑上面的显示hideBreadcrumb?: boolean;// 如果该路由会携带参数,且需要在tab页上面显示。则需要设置为truecarryParam?: boolean;// 隐藏所有子菜单hideChildrenInMenu?: boolean;// 当前激活的菜单。用于配置详情页时左侧激活的菜单路径currentActiveMenu?: string;// 当前路由不再标签页显示hideTab?: boolean;// 当前路由不再菜单显示hideMenu?: boolean;// 菜单排序,只对第一级有效orderNo?: number;// 忽略路由。用于在ROUTE_MAPPING以及BACK权限模式下,生成对应的菜单而忽略路由。ignoreRoute?: boolean;// 是否在子级菜单的完整path中忽略本级pathhidePathForChildren?: 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'), },}
若需要开启该功能,需要在动态路由的meta中设置如下两个参数:
{ 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 可以查看此处)。
项目中采用的是重定向方式
import { useRedo } from '/@/hooks/web/usePage';import { defineComponent } from 'vue';export default defineComponent({ setup() { const redo = useRedo(); // 执行刷新 redo(); return {}; },});
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 个条件
{ ..., // name name: 'Login', // 对应组件组件的name component: () => import('/@/views/sys/login/index.vue'), ... }, // /@/views/sys/login/index.vue export default defineComponent({ // 需要和路由的name一致 name:"Login" });
注意
keep-alive 生效的前提是:需要将路由的 name 属性及对应的页面的 name 设置成一样。因为:
include - 字符串或正则表达式,只有名称匹配的组件会被缓存
可在 router.meta 下配置
可以将 ignoreKeepAlive 配置成 true 即可关闭缓存。
export interface RouteMeta { // 是否忽略KeepAlive缓存 ignoreKeepAlive?: boolean;}