更新记录
1.0.0(2025-08-05) 下载此版本
详情查看readme.md
平台兼容性
uni-app(4.07)
Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
---|---|---|---|---|---|---|---|---|
- | √ | √ | √ | √ | √ | √ | √ | - |
微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 快应用-华为 | 快应用-联盟 |
---|---|---|---|---|---|---|---|---|---|---|
√ | - | - | - | - | - | - | - | - | - | - |
uni-app x(4.07)
Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
---|---|---|---|---|---|
- | - | - | - | - | - |
one-uni-router
基本用法
import { createUniRouter } from '@/uni_modules/one-uni-router';
function isLogin() {
return uni.getStorageSync("isLogin") == 1
}
const routerConfig = {
platform: process.env.UNI_PLATFORM,
routes: [
{
path: "/pages/index/index"
},
{
path: "/pages/index/404",
name: "404"
},
{
path: "/pages/index/my",
meta: {
needAuth: true
}
},
{
path: "/pages/index/login"
}
]
}
const router = createUniRouter(routerConfig);
router.routeNotFound((to) => {
console.log(to)
return {
name: '404',
query: {
from: to.path,
timestamp: Date.now()
}
}
})
router.beforeEach((to, from, next) => {
if (to.meta?.needAuth && !isLogin()) {
setTimeout(() => {
uni.navigateTo({
url: "/pages/index/login"
})
}, 300)
}
next();
});
router.afterEach((to, from) => {
})
export {
router
}
main.js中
... ...
import { router} from "@/one/router";
... ...
... ...
app.use(router)
... ...
可以结合'uni-read-pages-vite'
vite.config.js中
import TransformPages from 'uni-read-pages-vite';
define: {
... ...
ROUTES: new TransformPages(resolve(__dirname, 'src')).routes,
... ...
// 注入 manifest.json 配置
__H5_ROUTER_MODE__: getManifestSetting('h5.router.mode', 'hash'),
},
one/router.js中
const routerConfig = {
platform: process.env.UNI_PLATFORM,
//#ifdef H5
mode: __H5_ROUTER_MODE__,
//#endif
routes: [
...ROUTES,
{
path: '*',
redirect: (to) => {
console.log('🔄 Redirecting to 404:', to)
return { name: '404' }
}
},
]
}
其中h5下默认是hash,如果是其他的可以在读取manifest设置
h5下支持两种路由模式
// History模式(
const router = createUniRouter({
platform: 'h5',
mode: 'history', // 使用HTML5 History API
// URL: https://example.com/about
})
// Hash模式
const router = createUniRouter({
platform: 'h5',
mode: 'hash', // 使用URL hash
// URL: https://example.com/#/about
})
是否拦截uni中的跳转
const routerConfig = {
... ...
interceptUniMethods: true, // 默认拦截, 不拦截时只能使用router跳转方法
... ...
}
页面跳转
支持原生uni的方法跳转
// 1. 使用uni.navigateTo
uni.navigateTo({
url: '/pages/user/user?id=123',
success: () => {
console.log('navigateTo成功')
}
})
// 2. 使用uni.redirectTo
uni.redirectTo({
url: '/pages/login/login'
})
// 3. 使用uni.switchTab
uni.switchTab({
url: '/pages/index/index'
})
// 4. 使用uni.reLaunch
uni.reLaunch({
url: '/pages/index/index'
})
// 5. 使用uni.navigateBack
uni.navigateBack({
delta: 1
})
支持编程式导航
// 6. 编程式导航
console.log('\n6. 使用router.push编程式导航')
router.push('/pages/user/456')
console.log('\n7. 使用router.replace编程式替换')
router.replace('/pages/profile')
二者对应关系
uni.navigateTo({ url: '/about' }) // → router.push('/about')
uni.redirectTo({ url: '/login' }) // → router.replace('/login')
uni.switchTab({ url: '/home' }) // → router.replace('/home')
uni.reLaunch({ url: '/welcome' }) // → router.replace('/welcome')
uni.navigateBack({ delta: 1 }) // → router.back()
前置守卫
function isLoggedIn(): boolean {
// 模拟登录检查
return true
}
// 全局前置守卫
router.beforeEach((to, from, next) => {
console.log('=== 路由守卫信息 ===')
console.log('导航类型:', to.navType)
console.log('从:', from.path, '→ 到:', to.path)
console.log('路由名称:', to.name)
console.log('路由参数:', to.params)
console.log('查询参数:', to.query)
console.log('路由元信息:', to.meta)
// 根据to和from的数据执行不同的逻辑
switch (to.navType) {
case 'push':
// 可以在这里添加页面跳转的特殊处理
break
... ....
default:
console.log('🔍 未知导航类型:', to.navType)
}
// 权限检查
if (to.meta?.requiresAuth && !isLoggedIn()) {
console.log('❌ 需要登录,重定向到登录页')
next('/login')
return
}
next()
})
后置守卫
router.afterEach((to, from) => {
console.log('✅ 导航完成')
console.log('当前页面:', to.path)
console.log('页面标题:', to.meta?.title)
})
路由匹配
uni.navigateTo({ url: '/user/789' })
router.push('/user/789')
// 会匹配到 /user/:id 路由
uni.redirectTo({ url: '/settings' })
router.replace('/setting')
// 会匹配到 /settings 路由
注意带参数的路由需要定义在路由表中,pages.json无法带参数
routeNotFound
1. 在创建路由器时配置
import { createUniRouter } from 'one-uni-router'
const router = createUniRouter({
platform: process.env.VUE_APP_PLATFORM,
routes: [
{ path: '/home', name: 'Home', component: Home },
{ path: '/404', name: '404', component: NotFound }
],
routeNotFound: (to) => {
console.log('Route not found:', to.path)
return {
name: '404',
query: {
args: 'routeNotFound',
originalPath: to.path
}
}
}
})
2. 动态设置钩子
// 动态设置 routeNotFound 钩子
router.routeNotFound((to) => {
return {
path: '/404',
query: {
from: to.path,
timestamp: Date.now()
}
}
})
routeNotFound返回值类型
1. 返回字符串(路径重定向)
routeNotFound: (to) => {
// 简单重定向到 404 页面
return '/404'
}
2. 返回路由对象(完整重定向)
routeNotFound: (to) => {
return {
name: '404',
query: {
originalPath: to.path,
originalQuery: JSON.stringify(to.query)
}
}
}
3. 返回 null(不处理)
routeNotFound: (to) => {
// 记录日志但不重定向
console.log('Unhandled route:', to.path)
return null
}
实际应用场景
1. 基础 404 处理
const router = createUniRouter({
platform: process.env.VUE_APP_PLATFORM,
routes: [
{ path: '/home', name: 'Home' },
{ path: '/user/:id', name: 'User' },
{ path: '/404', name: '404' }
],
routeNotFound: (to) => ({
name: '404',
query: { args: 'routeNotFound' }
})
})
2. 带参数传递的 404 处理
const router = createUniRouter({
platform: process.env.VUE_APP_PLATFORM,
routes: [
// ... 其他路由
{ path: '/404', name: '404' }
],
routeNotFound: (to) => ({
name: '404',
query: {
...to.query, // 保留原始查询参数
notFound: 'true',
originalPath: to.path,
timestamp: Date.now().toString()
}
})
})
3. 条件重定向
const router = createUniRouter({
platform: process.env.VUE_APP_PLATFORM,
routes: [
{ path: '/home', name: 'Home'},
{ path: '/login', name: 'Login' },
{ path: '/404', name: '404'}
],
routeNotFound: (to) => {
// 根据路径前缀进行不同处理
if (to.path.startsWith('/admin')) {
return { name: 'Login', query: { redirect: to.path } }
}
if (to.path.startsWith('/api')) {
// API 路径不处理,让后端处理
return null
}
// 其他情况重定向到 404
return {
name: '404',
query: { originalPath: to.path }
}
}
})
meta的设置
const router = createUniRouter({
platform: 'mp-weixin',
interceptUniMethods: true,
routes: [
{
path: '/',
name: 'Home',
meta: {
title: '首页',
requiresAuth: false,
level: 1,
customData: {
theme: 'light',
analytics: true,
nested: {
deep: 'value',
array: [1, 2, 3]
}
}
}
},
{
path: '/profile',
name: 'Profile',
meta: {
title: '个人资料',
theme: "dark",
requiresAuth: true,
level: 2,
permissions: ['read', 'write', 'delete'],
config: {
showHeader: false,
showFooter: true
}
}
}
]
})
可以做不同配置在守卫中处理
高级路由匹配功能
注意 复杂路由需要自己定义,pages.json的path不能带:id啥得
功能特性
- ✅ 动态路由参数
- ✅ 可选参数
- ✅ 通配符匹配
- ✅ 正则表达式约束
- ✅ 可重复参数
- ✅ 路由重定向
- ✅ 路由优先级
- ✅ 动态路由管理
路由配置示例
import { createUniRouter } from 'one-uni-router'
const routes = [
// 静态路径匹配
{
path: '/home',
name: 'Home',
component: Home,
meta: { title: '首页' }
},
// 动态路由参数匹配
{
path: '/user/:id',
name: 'User',
component: User,
meta: { title: '用户详情' }
},
// 可选参数匹配
{
path: '/product/:category?',
name: 'Product',
component: Product,
meta: { title: '产品' }
},
// 通配符匹配
{
path: '/admin/(.*)',
name: 'Admin',
component: Admin,
meta: { title: '管理后台' }
},
// 可重复参数匹配
{
path: '/posts/:id+',
name: 'Posts',
component: Posts,
meta: { title: '文章列表' }
},
// 正则表达式匹配(只匹配数字)
{
path: '/users/:id(\\d+)',
name: 'Users',
component: Users,
meta: { title: '用户管理' }
},
// 复杂路径匹配
{
path: '/api/v:version(\\d+)/users/:userId(\\d+)',
name: 'ApiUser',
component: ApiUser,
meta: { title: 'API用户' }
},
// 路由重定向
{
path: '/old-home',
redirect: '/home'
},
// 动态重定向
{
path: '/profile',
redirect: (to) => ({
path: '/user/me',
query: to.query
})
},
// 404 路由(放在最后)
{
path: '/(.*)',
name: 'NotFound',
component: NotFound,
meta: { title: '页面未找到' }
}
]
const router = createUniRouter({
platform: 'h5',
mode: 'hash',
routes
})
路由匹配示例
1. 静态路径匹配
// 路由配置
{ path: '/home', name: 'Home' }
// 匹配的路径
'/home' ✅
'/home/' ✅ (自动处理尾部斜杠)
'/Home' ✅ (不区分大小写)
'/about' ❌
2. 动态路由参数
// 路由配置
{ path: '/user/:id', name: 'User' }
// 匹配示例
'/user/123' ✅ → params: { id: 123 }
'/user/john' ✅ → params: { id: 'john' }
'/user/123/profile' ❌
'/user' ❌
3. 可选参数
// 路由配置
{ path: '/product/:category?', name: 'Product' }
// 匹配示例
'/product' ✅ → params: {}
'/product/electronics' ✅ → params: { category: 'electronics' }
'/product/books/fiction' ❌
4. 通配符匹配
// 路由配置
{ path: '/admin/(.*)', name: 'Admin' }
// 匹配示例
'/admin' ✅
'/admin/dashboard' ✅
'/admin/users/123' ✅
'/admin/settings/profile' ✅
'/user/admin' ❌
5. 可重复参数
// 路由配置
{ path: '/posts/:id+', name: 'Posts' }
// 匹配示例
'/posts/123' ✅ → params: { id: ['123'] }
'/posts/123/456' ✅ → params: { id: ['123', '456'] }
'/posts/123/456/789' ✅ → params: { id: ['123', '456', '789'] }
'/posts' ❌
6. 正则表达式约束
// 路由配置
{ path: '/users/:id(\\d+)', name: 'Users' }
// 匹配示例
'/users/123' ✅ → params: { id: 123 }
'/users/456' ✅ → params: { id: 456 }
'/users/abc' ❌ (不匹配数字约束)
'/users/12a' ❌ (不匹配数字约束)
7. 复杂路径匹配
// 路由配置
{ path: '/api/v:version(\\d+)/users/:userId(\\d+)', name: 'ApiUser' }
// 匹配示例
'/api/v1/users/123' ✅ → params: { version: 1, userId: 123 }
'/api/v2/users/456' ✅ → params: { version: 2, userId: 456 }
'/api/v1.0/users/123' ❌ (version 不匹配数字)
'/api/v1/users/abc' ❌ (userId 不匹配数字)
路由重定向
静态重定向
// 简单重定向
{ path: '/old-home', redirect: '/home' }
// 使用
uni.navigateTo({ url: '/old-home' }) // 自动重定向到 /home
动态重定向
// 动态重定向函数
{
path: '/profile',
redirect: (to) => {
// 可以访问原始路由信息
return {
path: '/user/me',
query: to.query // 保持查询参数
}
}
}
// 使用
uni.navigateTo({ url: '/profile?tab=settings' })
// 重定向到 /user/me?tab=settings
路由优先级
路由按定义顺序匹配,先定义的路由优先级更高:
const routes = [
{ path: '/user/me', name: 'CurrentUser' }, // 优先级 1
{ path: '/user/:id', name: 'User' }, // 优先级 2
{ path: '/user/:id(\\d+)', name: 'NumericUser' }, // 优先级 3
]
// 匹配 '/user/me' → 'CurrentUser' (精确匹配优先)
// 匹配 '/user/123' → 'User' (先定义的动态路由优先)
// 匹配 '/user/abc' → 'User' (同上)
高级 API
生成路由路径
// 根据路由名称和参数生成路径
const path1 = router.generatePath('User', { id: 123 })
// 结果: '/user/123'
const path2 = router.generatePath('ApiUser', { version: 2, userId: 456 })
// 结果: '/api/v2/users/456'
const path3 = router.generatePath('Product', { category: 'books' })
// 结果: '/product/books'
const path4 = router.generatePath('Product') // 可选参数
// 结果: '/product'
动态添加路由
// 运行时添加新路由
router.addRoute({
path: '/settings/:section?',
name: 'Settings',
component: Settings,
meta: { title: '设置' }
})
// 立即可用
uni.navigateTo({ url: '/settings/profile' })
获取所有路由
// 获取当前所有路由配置
const allRoutes = router.getRoutes()
console.log(allRoutes.map(route => route.path))
参数类型自动转换
路由匹配器会自动转换参数类型:
// 数字参数自动转换
'/user/123' → params: { id: 123 } (number)
'/user/123.45' → params: { id: 123.45 } (number)
// 布尔参数自动转换
'/settings/true' → params: { enabled: true } (boolean)
'/settings/false' → params: { enabled: false } (boolean)
// 字符串参数保持原样
'/user/john' → params: { id: 'john' } (string)
// URL 解码
'/user/hello%20world' → params: { id: 'hello world' } (decoded)
最佳实践
1. 路由定义顺序
const routes = [
// 1. 精确匹配路由放在前面
{ path: '/user/me', name: 'CurrentUser' },
{ path: '/user/settings', name: 'UserSettings' },
// 2. 动态路由放在中间
{ path: '/user/:id', name: 'User' },
{ path: '/user/:id/posts', name: 'UserPosts' },
// 3. 通配符路由放在最后
{ path: '/admin/(.*)', name: 'Admin' },
{ path: '/(.*)', name: 'NotFound' }
]
2. 参数约束
// 使用正则约束确保参数格式正确
{ path: '/article/:id(\\d+)', name: 'Article' }, // 只匹配数字
{ path: '/user/:username([a-zA-Z0-9_]+)', name: 'User' }, // 只匹配用户名格式
{ path: '/date/:year(\\d{4})/:month(\\d{2})', name: 'Date' } // 匹配日期格式
调试
在开发环境下,路由匹配器会自动输出调试信息:
// 开发环境下会看到类似输出
📍 Added route: /user/:id (priority: 1)
✅ Route matched: /user/:id -> /user/123 { id: 123 }
❌ No route matched for: /non-existent
这个强大的路由匹配系统让 one-uni-router
能够处理各种复杂的路由场景,同时保持简单易用的 API。