Skip to content

createRouter()

创建 uni-app 路由器实例,是使用 Uni Router 的入口函数。

类型

ts
function createRouter(options: RouterOptions): Router

参数

options

路由器初始化选项,类型为 RouterOptions

ts
interface RouterOptions {
  routes: RouteConfig[]
  strict?: boolean
  interceptUniApi?: boolean
  guardTimeout?: number
  readyTimeout?: number
  paramsPersistent?: boolean
}

options.routes

  • 类型: RouteConfig[]
  • 必填: 是
  • 说明: 路由配置列表,需与 pages.json 中的页面声明保持一致

必须与 pages.json 一致

uni-app 的页面由 pages.json 静态声明,Uni Router 不会自动注册页面。routes 中的 path 必须能在 pages.json 中找到对应声明,否则导航会失败。

options.strict

  • 类型: boolean
  • 默认值: true
  • 说明: 是否启用严格模式
    • true:未匹配的命名路由将抛出 ROUTE_NOT_FOUND 错误
    • false:未匹配的命名路由仅输出警告,并使用名称作为路径回退

何时关闭严格模式

仅在迁移阶段或快速原型开发时关闭。生产环境建议保持 true,以便尽早发现路由配置错误。

options.interceptUniApi

  • 类型: boolean
  • 默认值: false
  • 说明: 是否拦截 uni 原生导航 API(navigateTo / redirectTo / switchTab / reLaunch / navigateBack

启用后直接调用 uni.navigateTo() 等方法将被拦截并转由路由器处理,确保路由守卫(beforeEach / beforeResolve / afterEach)始终生效。

启用后的副作用

  1. 直接调用 uni.navigateTo() 等方法的 success / fail 回调将不会被触发(原始调用被阻止后转由路由器执行)
  2. H5 平台 TabBar 点击会触发 uni.switchTab,已做特殊处理:放行原始调用并在 success 中同步路由状态
  3. 建议统一使用 router.push() / router.replace() / router.back() 进行导航

详见拦截器机制

options.guardTimeout

  • 类型: number
  • 默认值: 10000(10 秒)
  • 说明: 守卫超时时间(毫秒)。当守卫函数在此时间内既未调用 next() 也未返回 rejected Promise 时,将输出警告并自动中止导航以防止永久挂起
ts
const router = createRouter({
  routes: [...],
  guardTimeout: 30000 // 守卫中异步请求较慢时调大超时
})

调整建议

  • 守卫中包含网络请求:建议 30000(30 秒)
  • 纯同步守卫:保持默认 10000 即可
  • 设为 0 可禁用超时保护(不推荐,可能导致导航永久挂起)

options.readyTimeout

  • 类型: number
  • 默认值: 0(永不超时)
  • 说明: 路由器就绪超时时间(毫秒)。当路由器在此时间内未能完成初始化时,await router.isReady() 将被 reject,防止路由器初始化异常时 Promise 永久挂起
ts
const router = createRouter({
  routes: [...],
  readyTimeout: 5000 // 5 秒内未就绪则 reject isReady() Promise
})

options.paramsPersistent

  • 类型: boolean
  • 默认值: false
  • 说明: 页面参数持久化默认值
    • true:所有 params 默认通过 uni.setStorageSync 持久化存储,H5 刷新后仍可读取
    • falseparams 仅存储在内存中,页面关闭后数据丢失
    • 单次导航可通过 persistent 选项覆盖此默认值
ts
const router = createRouter({
  routes: [...],
  paramsPersistent: true // 所有 params 默认持久化
})

// 单次导航覆盖
await router.push({ path: '/detail', params: { id: 123 }, persistent: false }) // 不持久化

持久化的代价

持久化会写入 storage,频繁使用大对象会增加存储开销。建议仅在需要 H5 刷新后恢复数据的场景启用。

返回值

返回 Router 实例。

示例

最小配置

ts
import { createRouter } from '@meng-xi/uni-router'

const router = createRouter({
  routes: [
    { path: 'pages/index/index', name: 'home', meta: { title: '首页' } },
    { path: 'pages/about/about', name: 'about', meta: { title: '关于' } }
  ]
})

export default router

完整配置

ts
import { createRouter } from '@meng-xi/uni-router'
import type { RouteConfig } from '@meng-xi/uni-router'

const routes: RouteConfig[] = [
  { path: 'pages/index/index', name: 'home', meta: { title: '首页', isTab: true } },
  { path: 'pages/about/about', name: 'about', meta: { title: '关于', requireAuth: true } },
  { path: 'pages/user/user', name: 'user', meta: { title: '我的', isTab: true } },
  { path: 'pages/login/login', name: 'login', meta: { title: '登录' } }
]

const router = createRouter({
  routes,
  strict: true,              // 严格模式,未匹配路由抛错
  interceptUniApi: true,     // 拦截原生 API,统一守卫流程
  guardTimeout: 15000,       // 守卫超时 15 秒
  readyTimeout: 5000,        // 就绪超时 5 秒
  paramsPersistent: false    // params 默认不持久化
})

export default router

注册到 Vue 应用

ts
// src/main.ts
import { createSSRApp } from 'vue'
import App from './App.vue'
import router from './router'

export function createApp() {
  const app = createSSRApp(App)
  app.use(router)
  return { app }
}

安装时机

app.use(router) 会触发 install,注册全局属性 $router / $route,并通过 provide 注入路由器实例,使 useRouter() / useRoute() 可用。同时标记路由器为就绪状态,所有等待中的 isReady() Promise 将被 resolve。

在 Pinia store 中使用路由器

由于 app.use(router) 后路由器即就绪,可在 Pinia store 中安全使用:

ts
// src/store/user.ts
import { defineStore } from 'pinia'
import router from '@/router'

export const useUserStore = defineStore('user', () => {
  async function logout() {
    // 清除登录状态
    localStorage.removeItem('token')
    // 跳转登录页,清空栈
    await router.relaunch({ name: 'login' })
  }

  return { logout }
})

避免在模块顶层调用导航

不要在模块顶层直接调用 router.push(),应在函数内部调用。模块顶层执行时 Vue 应用可能尚未挂载,页面栈为空会导致导航失败。

常见问题

Q: 路由配置必须与 pages.json 完全一致吗?

A: path 必须能在 pages.json 中找到对应声明。namemeta 是 Uni Router 扩展字段,无需在 pages.json 中配置。建议使用 @meng-xi/vite-plugin 自动生成路由配置,避免手动维护不一致。

Q: interceptUniApi 启用后,原有 uni.navigateTo 代码还能用吗?

A: 能用,但行为会变化。启用后 uni.navigateTo 会被拦截转由路由器处理,success / fail 回调不会触发。建议逐步迁移到 router.push() 等 API。

Q: 多个路由器实例能共存吗?

A: 技术上可以创建多个,但不推荐。uni-app 是单页面栈模型,多个路由器实例会导致状态混乱。始终使用单一路由器实例。

下一步

Released under the MIT License.