RouteMeta
路由元信息,用于描述路由的附加属性。通过 RouteConfig.meta 配置,在守卫、afterEach 钩子、组件中通过 to.meta / route.meta 访问。
类型定义
ts
interface RouteMeta {
title?: string
isTab?: boolean
requireAuth?: boolean
animation?: NavigationAnimation
[key: string]: any
}内置属性
title
- 类型:
string | undefined - 说明: 页面标题,可在
afterEach钩子中用于设置导航栏标题
ts
const routes = [
{ path: 'pages/index/index', name: 'home', meta: { title: '首页' } },
{ path: 'pages/about/about', name: 'about', meta: { title: '关于我们' } }
]
// afterEach 中自动设置标题
router.afterEach((to) => {
if (to.meta.title) {
uni.setNavigationBarTitle({ title: to.meta.title as string })
}
})isTab
- 类型:
boolean | undefined - 说明: 是否为 TabBar 页面。路由器根据此字段自动选择导航 API
true→uni.switchTabfalse/ 未设置 →uni.navigateTo/uni.redirectTo
必须与 pages.json 一致
meta.isTab 必须与 pages.json 的 tabBar.list 声明一致。如果声明了 isTab: true 但不在 tabBar.list 中,uni.switchTab 会失败;反之亦然。
建议使用 @meng-xi/vite-plugin 自动生成路由配置,会自动识别 TabBar 页面并设置 isTab。
ts
const routes = [
{ path: 'pages/index/index', name: 'home', meta: { isTab: true } }, // TabBar 页面
{ path: 'pages/about/about', name: 'about', meta: { isTab: false } } // 普通页面
]requireAuth
- 类型:
boolean | undefined - 说明: 是否需要登录认证,常与
beforeEach守卫配合使用
ts
const routes = [
{ path: 'pages/index/index', name: 'home', meta: { requireAuth: false } },
{ path: 'pages/about/about', name: 'about', meta: { requireAuth: true } },
{ path: 'pages/user/user', name: 'user', meta: { requireAuth: true } }
]
// 全局前置守卫
router.beforeEach((to, from) => {
const isLoggedIn = !!uni.getStorageSync('token')
if (to.meta.requireAuth && !isLoggedIn) {
return { name: 'login', query: { redirect: to.fullPath } }
} else {
return
}
})animation
- 类型:
NavigationAnimation | undefined - 说明: 默认导航动画,可被
push/replace/back调用时传入的animation参数覆盖。App 端为原生窗口动画,H5 端由本库通过 CSS 过渡实现(仅push/back生效),小程序自动忽略
ts
interface NavigationAnimation {
type: UniAnimationType
duration?: number // 默认 300ms
}动画优先级:调用时传入 > meta.animation > uni 默认值
ts
const routes = [
{
path: 'pages/about/about',
name: 'about',
meta: { animation: { type: 'fade-in', duration: 300 } }
},
{
path: 'pages/detail/detail',
name: 'detail',
meta: { animation: { type: 'slide-in-bottom', duration: 500 } }
}
]
// 使用 meta 中的默认动画
await router.push({ name: 'about' }) // fade-in, 300ms
// 调用时覆盖
await router.push({ name: 'about', animation: { type: 'slide-in-right' } }) // slide-in-right, 300ms平台限制
动画在 App 端为原生窗口动画(所有导航方式生效),H5 端通过 CSS 过渡实现(仅 push / back 生效,replace / relaunch 无动画),小程序端由宿主控制、无法自定义。
UniAnimationType 可选值(显示动画 navigateTo 与关闭动画 navigateBack):
- 显示动画:
'slide-in-right'/'slide-in-left'/'slide-in-top'/'slide-in-bottom'/'pop-in'/'fade-in'/'zoom-out'/'zoom-fade-out' - 关闭动画:
'slide-out-right'/'slide-out-left'/'slide-out-top'/'slide-out-bottom'/'pop-out'/'fade-out'/'zoom-in'/'zoom-fade-in' - 通用:
'none'(无动画)/'auto'(自动选择)
动画类型本身没有"默认值",仅
duration默认300ms;如未指定type,push/back使用 uni 的默认过渡。
自定义扩展
通过索引签名 [key: string]: any 支持任意自定义字段:
ts
const routes = [
{
path: 'pages/article/detail',
name: 'article-detail',
meta: {
title: '文章详情',
requireAuth: false,
keepAlive: true, // 自定义:是否缓存
permissions: ['read', 'comment'], // 自定义:所需权限
layout: 'default', // 自定义:布局类型
breadcrumb: ['首页', '文章', '详情'] // 自定义:面包屑
}
}
]类型增强(推荐)
通过 TypeScript 的声明合并为 RouteMeta 添加类型提示:
ts
// src/types/router.d.ts
declare module '@meng-xi/uni-router' {
interface RouteMeta {
// 自定义字段
keepAlive?: boolean
permissions?: string[]
layout?: 'default' | 'simple' | 'full'
breadcrumb?: string[]
// 业务字段
roles?: string[] // 所需角色
module?: string // 所属模块
cacheKey?: string // 缓存键
}
}增强后,在路由配置和守卫中访问自定义字段会有类型提示:
ts
const routes: RouteConfig[] = [
{
path: 'pages/admin/admin',
name: 'admin',
meta: {
title: '管理后台',
requireAuth: true,
roles: ['admin', 'superadmin'], // ✅ 有类型提示
module: 'admin' // ✅ 有类型提示
}
}
]
// 守卫中访问
router.beforeEach((to, from) => {
if (to.meta.roles) {
const userRoles = getUserRoles()
if (!to.meta.roles.some(r => userRoles.includes(r))) {
return { name: '403' }
}
}
return
})类型增强的好处
- 类型安全:拼写错误会在编译时报错
- 自动补全:IDE 会提示可用的字段
- 文档化:团队成员能直观看到支持哪些 meta 字段
实战应用
权限控制
ts
// 扩展类型
declare module '@meng-xi/uni-router' {
interface RouteMeta {
roles?: string[]
permissions?: string[]
}
}
const routes: RouteConfig[] = [
{
path: 'pages/admin/admin',
name: 'admin',
meta: {
title: '管理后台',
requireAuth: true,
roles: ['admin'],
permissions: ['read', 'write', 'delete']
}
}
]
router.beforeEach((to, from) => {
if (to.meta.roles && !hasRole(to.meta.roles)) {
return { name: '403' }
}
if (to.meta.permissions && !hasPermission(to.meta.permissions)) {
return { name: '403' }
}
return
})动态标题
ts
const routes = [
{ path: 'pages/index/index', name: 'home', meta: { title: '首页' } },
{ path: 'pages/about/about', name: 'about', meta: { title: '关于我们' } },
{ path: 'pages/user/user', name: 'user', meta: { title: '个人中心' } }
]
// afterEach 中统一设置标题
router.afterEach((to) => {
const title = to.meta.title as string | undefined
uni.setNavigationBarTitle({ title: title || '默认标题' })
})页面缓存控制
ts
declare module '@meng-xi/uni-router' {
interface RouteMeta {
keepAlive?: boolean
cacheKey?: string
}
}
const routes = [
{
path: 'pages/list/list',
name: 'list',
meta: {
keepAlive: true,
cacheKey: 'list-data' // 缓存键
}
}
]
// 在页面中根据 meta 决定是否缓存
const route = useRoute()
const shouldCache = computed(() => route.value.meta.keepAlive === true)布局切换
ts
declare module '@meng-xi/uni-router' {
interface RouteMeta {
layout?: 'default' | 'simple' | 'full'
}
}
const routes = [
{ path: 'pages/index/index', name: 'home', meta: { layout: 'default' } },
{ path: 'pages/login/login', name: 'login', meta: { layout: 'simple' } },
{ path: 'pages/editor/editor', name: 'editor', meta: { layout: 'full' } }
]
// App.vue 中根据 meta 切换布局
const route = useRoute()
const currentLayout = computed(() => route.value.meta.layout || 'default')埋点上报
ts
declare module '@meng-xi/uni-router' {
interface RouteMeta {
trackName?: string // 埋点页面名
trackParams?: Record<string, any> // 埋点参数
}
}
const routes = [
{
path: 'pages/detail/detail',
name: 'detail',
meta: {
trackName: 'detail_page',
trackParams: { source: 'home' }
}
}
]
router.afterEach((to) => {
if (to.meta.trackName) {
trackPageView(to.meta.trackName, to.meta.trackParams)
}
})下一步
- RouteConfig 类型 — 路由配置项
- 路由元信息指南 — meta 的深入使用
- 实战指南 — 完整业务方案
