UniApp基于Vue.js实现了一套跨平台的路由管理系统,其核心原理是通过维护页面栈来管理应用内不同页面之间的跳转关系。在小程序端,UniApp的路由系统会映射到对应平台的原生导航机制;在H5端则基于HTML5 History API实现;而App端则采用原生导航栏结合Webview管理的方式。
页面栈管理遵循以下规则:
• 最大页面栈深度为10层(微信小程序规范)
• 页面跳转方式影响栈结构(push/pop/replace)
• 页面生命周期与栈变化密切相关
路由系统的核心配置文件是pages.json
,位于项目根目录。该文件采用JSON格式,包含以下主要配置节点:
{
"pages": [
{
"path": "pages/index/index",
"style": {...}
}
],
"globalStyle": {...},
"tabBar": {...},
"condition": {...},
"subPackages": [...],
"preloadRule": {...}
}
特性 | 微信小程序 | H5 | App | 支付宝小程序 |
---|---|---|---|---|
页面栈最大深度 | 10 | 无限制 | 10 | 10 |
原生导航栏支持 | ✔️ | ✔️ | ✔️ | ✔️ |
自定义导航栏性能 | 一般 | 优 | 优 | 一般 |
路由传参方式 | URL | URL | URL | URL |
动态修改导航栏 | API | CSS | 原生API | API |
页面预加载 | ✔️ | ✔️ | ✔️ | ❌ |
全局样式配置影响所有页面的默认表现,优先级低于页面级样式配置。
"globalStyle": {
"navigationBarTextStyle": "white",
"navigationBarTitleText": "全局标题",
"navigationBarBackgroundColor": "#007AFF",
"backgroundColor": "#F8F8F8"
}
"globalStyle": {
"enablePullDownRefresh": true,
"onReachBottomDistance": 100,
"backgroundTextStyle": "dark"
}
"globalStyle": {
"mp-weixin": {
"navigationBarTitleText": "微信专属标题"
},
"app-plus": {
"titleNView": {
"buttons": [...]
}
}
}
定义应用页面路径及页面级样式,数组第一项为首页入口。
"pages": [
{
"path": "pages/home/home",
"style": {
"navigationBarTitleText": "首页",
"enablePullDownRefresh": true
}
}
]
全局样式 → 页面样式 → 组件样式 → 内联样式
{
"path": "pages/detail/_id",
"style": {
"navigationBarTitleText": "详情页",
"disableScroll": true
}
}
实现多Tab应用的核心配置,支持丰富的自定义选项。
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#007AFF",
"borderStyle": "white",
"backgroundColor": "#F8F8F8",
"list": [
{
"pagePath": "pages/home/home",
"text": "首页",
"iconPath": "static/tab-home.png",
"selectedIconPath": "static/tab-home-active.png"
}
]
}
"midButton": {
"width": "80px",
"height": "50px",
"text": "发布",
"iconPath": "static/mid-button.png",
"backgroundImage": "static/mid-bg.png"
}
uni.showTabBarRedDot({
index: 1
})
uni.setTabBarItem({
index: 0,
text: '新首页',
iconPath: 'static/new-icon.png'
})
优化小程序体积的重要机制,支持按需加载。
"subPackages": [
{
"root": "packageA",
"pages": [
{
"path": "page1/page1",
"style": {...}
}
]
}
]
"preloadRule": {
"pages/home/home": {
"network": "wifi",
"packages": ["packageA"]
}
}
"condition": {
"current": 0,
"list": [
{
"name": "测试环境",
"path": "pages/debug/debug",
"query": "env=test"
}
]
}
方法 | 说明 | 栈变化 |
---|---|---|
uni.navigateTo | 保留当前页,打开新页 | push |
uni.redirectTo | 关闭当前页,打开新页 | replace |
uni.reLaunch | 关闭所有页,打开新页 | clear+push |
uni.switchTab | 切换Tab页 | clear+push |
uni.navigateBack | 返回上一页 | pop |
// 跳转时传参
uni.navigateTo({
url: '/pages/detail/detail?id=1&name=test'
})
// 页面接收参数
export default {
onLoad(options) {
console.log(options.id) // 1
}
}
// 对象参数序列化
const params = {
id: 1,
data: { name: 'test' }
}
uni.navigateTo({
url: `/pages/detail/detail?params=${encodeURIComponent(JSON.stringify(params))}`
})
// 接收端解析
const params = JSON.parse(decodeURIComponent(options.params))
完整生命周期流程:
创建阶段:
beforeCreate → onLoad → onShow → onReady
运行阶段:
onHide/onShow → onResize → onPullDownRefresh → onReachBottom → onPageScroll
销毁阶段:
onUnload → beforeDestroy → destroyed
通过拦截器实现全局路由守卫:
// main.js
const routerInterceptor = {
navigateTo: function(options) {
if (!checkAuth()) {
return uni.redirectTo({ url: '/pages/login/login' })
}
return uni.navigateTo(options)
},
// 其他方法拦截...
}
function createInterceptor() {
['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].forEach(apiName => {
const original = uni[apiName]
uni[apiName] = function(options) {
return routerInterceptor[apiName](options) || original.call(uni, options)
}
})
}
createInterceptor()
实现步骤:
"globalStyle": {
"navigationStyle": "custom"
}
{{ title }}
配置页面切换动画:
{
"path": "pages/detail/detail",
"style": {
"app-plus": {
"animationType": "slide-in-right",
"animationDuration": 300
}
}
}
宽屏设备适配方案:
"leftWindow": {
"path": "responsive/left-window.vue",
"style": {
"width": "300px"
}
},
"rightWindow": {
"path": "responsive/right-window.vue",
"matchMedia": {
"minWidth": 768
}
}
"preloadRule": {
"pages/detail/detail": {
"network": "wifi",
"packages": ["__APP__"]
}
}
// 使用easycom自动引入
"easycom": {
"autoscan": true,
"custom": {
"^uni-(.*)": "@/components/uni-$1.vue"
}
}
问题:URL参数长度限制
解决方案:
问题:超过10层页面栈导致无法跳转
解决方案:
function smartNavigateTo(url) {
const pages = getCurrentPages()
if (pages.length >= 9) {
uni.redirectTo({ url })
} else {
uni.navigateTo({ url })
}
}
优化策略:
典型问题处理:
.navbar {
height: calc(44px + env(safe-area-inset-top));
padding-top: env(safe-area-inset-top);
}
// 统一处理下拉刷新
onPullDownRefresh() {
this.loadData().finally(() => {
#ifdef H5
this.$nextTick(() => uni.stopPullDownRefresh())
#else
uni.stopPullDownRefresh()
#endif
})
}
uni.onTabBarMidButtonTap(() => {
// 处理中间按钮点击
})
推荐目录结构:
├── api
├── components
│ └── common
├── pages
│ ├── home
│ └── user
├── static
│ ├── images
│ └── fonts
├── store
├── utils
└── uni_modules
console.log(getCurrentPages())
onLoad(options) {
console.log('路由参数:', options)
}
condition
配置快速调试特定页面常见内存泄漏场景:
优化建议:
onUnload() {
// 清理操作
this.timer && clearInterval(this.timer)
uni.$off('event', this.handler)
}
路由相关插件推荐:
uni-simple-router:功能强大的路由管理插件
UniApp微前端实现方案:
前后端路由统一方案: