在 uni-app 中,路由指的是页面之间的跳转与导航机制。它基于页面栈进行管理,支持声明式和编程式两种用法。下面详细介绍路由的配置、跳转方式、传参、页面栈管理等核心内容。
一、路由配置:pages.json
所有页面路径必须在 pages.json 的 pages 数组中声明,才能被访问。
{
"pages": [
{
"path": "pages/index/index", // 页面路径
"style": { ... } // 页面样式配置
},
{
"path": "pages/detail/detail",
"style": { ... }
}
],
"tabBar": { ... } // 底部选项卡配置
}
-
pages 数组的第一项为首页。
-
如果页面是
tabBar页面,则需要在tabBar中配置对应的pagePath。
二、路由跳转方式
uni-app 提供了两种跳转方式:声明式 (使用 <navigator> 组件)和 编程式(调用 API)。
1. 声明式跳转
使用 <navigator> 组件,类似 HTML 中的 <a> 标签。
<!-- 普通跳转,保留当前页面 -->
<navigator url="/pages/detail/detail" hover-class="navigator-hover">
跳转到详情页
</navigator>
<!-- 重定向跳转,关闭当前页面 -->
<navigator url="/pages/detail/detail" open-type="redirect">
重定向到详情页
</navigator>
<!-- 跳转到 tabBar 页面 -->
<navigator url="/pages/user/user" open-type="switchTab">
跳转到我的
</navigator>
open-type 的可选值:
-
navigate:保留当前页面,跳转到非 tabBar 页面(默认)。 -
redirect:关闭当前页面,跳转到非 tabBar 页面。 -
switchTab:跳转到 tabBar 页面,关闭所有非 tabBar 页面。 -
reLaunch:关闭所有页面,跳转到任意页面(通常用于登录后跳转)。 -
navigateBack:返回上一页或多级页面(需要配合delta属性)。
2. 编程式跳转
通过 uni 提供的 API 进行跳转,更灵活,可以在 JavaScript 中调用。
uni.navigateTo
保留当前页面,跳转到应用内的某个非 tabBar 页面。
uni.navigateTo({
url: '/pages/detail/detail?id=123&name=uni-app'
});
uni.redirectTo
关闭当前页面,跳转到应用内的某个非 tabBar 页面。
uni.redirectTo({
url: '/pages/detail/detail'
});
uni.switchTab
跳转到 tabBar 页面,并关闭所有非 tabBar 页面。
uni.switchTab({
url: '/pages/user/user'
});
uni.reLaunch
关闭所有页面,打开到应用内的某个页面(常用于登录后跳转首页)。
uni.reLaunch({
url: '/pages/index/index'
});
uni.navigateBack
返回上一页或多级页面。
// 返回上一页
uni.navigateBack();
// 返回上两页
uni.navigateBack({
delta: 2
});
三、路由传参与接收
1. 传递参数
参数通过 url 的查询字符串传递(?key=value),多个参数用 & 连接。
uni.navigateTo({
url: '/pages/detail/detail?id=123&title=Hello'
});
如果需要传递对象等复杂数据,可以先使用 encodeURIComponent 转为字符串。
let data = { id: 123, name: 'uni-app' };
uni.navigateTo({
url: '/pages/detail/detail?data=' + encodeURIComponent(JSON.stringify(data))
});
2. 接收参数
在目标页面的 onLoad 生命周期函数中接收,参数以对象形式传入。
export default {
onLoad(options) {
console.log(options.id); // 123
console.log(options.title); // Hello
// 如果传递了 JSON 数据
if (options.data) {
let data = JSON.parse(decodeURIComponent(options.data));
console.log(data);
}
}
}
注意 :onLoad 只会在页面第一次加载时触发,如果页面已存在于页面栈中且使用 navigateTo 打开,不会重新触发 onLoad,此时可以通过其他方式(如 $on/$emit 或全局变量)传递新数据。
四、页面栈管理
uni-app 使用 页面栈 来管理页面,遵循"先进后出"的原则。常用 API 对应的页面栈变化:
| API | 页面栈变化 |
|---|---|
navigateTo |
新页面入栈 |
redirectTo |
当前页面出栈,新页面入栈 |
navigateBack |
当前页面出栈(可指定出栈层数) |
switchTab |
清空所有非 tabBar 页面,跳转到指定 tabBar 页 |
reLaunch |
清空所有页面,新页面入栈 |
可以通过 getCurrentPages() 获取当前页面栈实例数组,数组中第一个元素为首页,最后一个为当前页。
let pages = getCurrentPages(); // 获取页面栈
let currentPage = pages[pages.length - 1]; // 当前页面实例
let prevPage = pages[pages.length - 2]; // 上一个页面实例
借助页面实例,可以在返回时传递数据给上一页:
// 在 B 页面
let pages = getCurrentPages();
let prevPage = pages[pages.length - 2];
prevPage.$data.someData = '需要传递的数据';
uni.navigateBack();
五、路由拦截与权限控制
虽然 uni-app 没有内置全局路由守卫,但可以通过在 App.vue 的 onLaunch 中监听路由跳转,或封装统一的跳转函数来实现权限控制。
简单封装示例:
// utils/router.js
function navigateTo(url, needLogin = false) {
if (needLogin && !uni.getStorageSync('token')) {
uni.navigateTo({
url: '/pages/login/login'
});
return;
}
uni.navigateTo({ url });
}
export default { navigateTo };
然后在页面中使用:
import router from '@/utils/router';
router.navigateTo('/pages/detail/detail', true);
六、注意事项
-
页面路径必须已注册 :跳转的页面需在
pages.json的pages中定义。 -
tabBar 页面限制 :
navigateTo和redirectTo不能跳转到 tabBar 页面,必须使用switchTab。 -
页面栈最大深度 :
navigateTo最多可打开 10 层页面,超出会触发失败回调。 -
H5 兼容性 :在 H5 端,如果使用了
history模式路由,跳转时url中的#需注意处理;uni-app 推荐使用hash模式。 -
动画效果 :可通过
animationType和animationDuration自定义页面切换动画(App 端支持)。 -
页面生命周期 :路由跳转会触发相应页面的生命周期(
onLoad、onShow、onHide等),需合理使用。