路由与页面跳转是uni-app应用的核心功能之一,本文将详细介绍各种跳转方式及其最佳实践,帮助你构建流畅的页面导航体验。
1. 基础路由方法
1.1 页面跳转方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| uni.navigateTo({ url: '/pages/detail/detail?id=1', success: function(res) { console.log('跳转成功') }, fail: function(err) { console.error('跳转失败:', err) } })
uni.redirectTo({ url: '/pages/index/index' })
uni.reLaunch({ url: '/pages/home/home' })
uni.navigateBack({ delta: 1 })
uni.switchTab({ url: '/pages/user/user' })
|
1.2 参数传递
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| uni.navigateTo({ url: '/pages/detail/detail?id=1&type=product&data=' + encodeURIComponent(JSON.stringify(data)) })
export default { onLoad(options) { const id = options.id const type = options.type const data = JSON.parse(decodeURIComponent(options.data)) console.log('接收到的参数:', id, type, data) } }
|
2. 路由拦截与权限控制
2.1 全局路由拦截
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| import Vue from 'vue' import store from './store'
const whiteList = ['/pages/login/login', '/pages/register/register']
Vue.prototype.$beforeRouter = function(to) { return new Promise((resolve, reject) => { if (whiteList.includes(to)) { resolve() return } const token = uni.getStorageSync('token') if (!token) { uni.showToast({ title: '请先登录', icon: 'none' }) uni.navigateTo({ url: '/pages/login/login' }) reject(new Error('未登录')) return } const userInfo = store.state.user.userInfo if (to.requiresAuth && !userInfo.permissions.includes(to.permission)) { uni.showToast({ title: '暂无权限访问', icon: 'none' }) reject(new Error('无权限')) return } resolve() }) }
export default { async onLoad() { try { await this.$beforeRouter('/pages/user/user') } catch (err) { console.error('路由拦截:', err) } } }
|
2.2 页面级权限控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| export default { data() { return { hasPermission: false } }, onLoad() { this.checkPermission() }, methods: { checkPermission() { const userPermissions = this.$store.state.user.permissions const pagePermission = this.$options.permission if (!pagePermission) { this.hasPermission = true return } this.hasPermission = userPermissions.includes(pagePermission) if (!this.hasPermission) { uni.showModal({ title: '提示', content: '暂无访问权限', showCancel: false, success: () => { uni.navigateBack() } }) } } } }
import authMixin from '@/mixins/auth'
export default { mixins: [authMixin], permission: 'user:edit' }
|
3. 页面通信方案
3.1 页面间事件通信
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| onLoad() { uni.$on('updateList', this.handleUpdateList) }, onUnload() { uni.$off('updateList', this.handleUpdateList) }, methods: { handleUpdateList(data) { console.log('收到更新数据:', data) this.refreshList() } }
methods: { submitSuccess() { uni.$emit('updateList', { type: 'add', data: this.formData }) uni.navigateBack() } }
|
3.2 页面栈管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| class PageManager { static getCurrentPages() { const pages = getCurrentPages() return pages } static getPrevPage(delta = 1) { const pages = this.getCurrentPages() const prevPage = pages[pages.length - 1 - delta] return prevPage } static callPrevPageMethod(methodName, args, delta = 1) { const prevPage = this.getPrevPage(delta) if (prevPage && typeof prevPage[methodName] === 'function') { return prevPage[methodName](args) } return null } static canBack() { const pages = this.getCurrentPages() return pages.length > 1 } }
export default PageManager
import PageManager from '@/utils/page'
PageManager.callPrevPageMethod('refreshData', { type: 'update' })
if (PageManager.canBack()) { uni.navigateBack() } else { uni.reLaunch({ url: '/pages/index/index' }) }
|
4. 路由动画与转场效果
4.1 基础动画配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { "pages": [{ "path": "pages/index/index", "style": { "navigationBarTitleText": "首页", "app-plus": { "animationType": "slide-in-right", "animationDuration": 300 } } }] }
uni.navigateTo({ url: '/pages/detail/detail', animationType: 'slide-in-bottom', animationDuration: 300 })
|
4.2 自定义转场动画
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| <!-- components/page-transition.vue --> <template> <view class="page-transition" :class="[transitionClass]"> <slot></slot> </view> </template>
<script> export default { data() { return { transitionClass: '' } }, methods: { enter() { this.transitionClass = 'slide-enter' setTimeout(() => { this.transitionClass = 'slide-enter-active' }, 50) }, leave() { this.transitionClass = 'slide-leave' setTimeout(() => { this.transitionClass = 'slide-leave-active' }, 50) } } } </script>
<style> .page-transition { position: absolute; width: 100%; height: 100%; transition: all 0.3s ease; }
.slide-enter { transform: translateX(100%); } .slide-enter-active { transform: translateX(0); } .slide-leave { transform: translateX(0); } .slide-leave-active { transform: translateX(-100%); } </style>
|
5. 常见问题与解决方案
5.1 页面栈溢出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| function checkPageStack() { const pages = getCurrentPages() const maxStack = 10 if (pages.length >= maxStack) { uni.showModal({ title: '提示', content: '页面层级过深,是否返回首页?', success: (res) => { if (res.confirm) { uni.reLaunch({ url: '/pages/index/index' }) } } }) return false } return true }
methods: { navigateToDetail() { if (!checkPageStack()) return uni.navigateTo({ url: '/pages/detail/detail' }) } }
|
5.2 参数长度限制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| function handleLongParams(params) { if (typeof params !== 'string') { params = JSON.stringify(params) } if (params.length > 2048) { const key = 'temp_params_' + Date.now() uni.setStorageSync(key, params) return key } return params }
const params = handleLongParams(this.longData) uni.navigateTo({ url: `/pages/detail/detail?key=${params}` })
onLoad(options) { let data = options.key if (data.startsWith('temp_params_')) { data = uni.getStorageSync(data) uni.removeStorageSync(data) } this.handleData(JSON.parse(data)) }
|
6. 最佳实践建议
- 合理使用页面跳转方式
- 实现统一的路由拦截
- 注意页面栈管理
- 优化转场动画
- 处理异常情况
7. 总结
- 掌握基础路由方法
- 实现权限控制
- 处理页面通信
- 优化用户体验
- 解决常见问题
如果觉得文章对你有帮助,欢迎点赞、评论、分享,你的支持是我继续创作的动力!