在 UniApp 跨端开发中,路由是连接页面的核心纽带,合理的路由配置不仅能保障页面跳转的稳定性,还能提升用户体验。本文以实际项目中的路由代码为例,拆解 UniApp 基于uni-simple-router的路由配置逻辑,重点解析 404 页面跳转、全局路由守卫、跨端适配等关键场景的实现思路。
一、路由配置核心背景
uni-simple-router是 UniApp 生态中主流的路由扩展库,相比原生路由,它提供了类似 Vue Router 的守卫、路由重定向、通配符匹配等能力,适配多端(小程序、APP、H5)的路由特性差异。本文分析的代码正是基于该库搭建的 UniApp 路由体系,核心解决「跨端路由适配」「权限控制」「异常页面处理」三大问题。
完整路由配置文件(router/index.js)
typescript
// 引入uni-simple-router核心方法:创建路由实例、挂载路由
import { RouterMount, createRouter } from './uni-simple-router.js'
// 引入Vuex仓库,用于登录状态、权限控制
import store from '@/shopro/store'
// 引入项目自定义路由表(需提前在routes.js中定义所有页面路由)
import ROUTES from './routes.js'
/**
* 创建路由实例
* @param {String} platform - 运行环境(由环境变量控制,如mp-weixin、app-plus、h5)
* @param {Object} applet - 小程序端专属配置
* @param {Function} routerErrorEach - 路由错误统一处理函数
* @param {Array} routes - 合并项目路由表 + 404兜底路由
*/
const router = createRouter({
// 指定运行平台,适配多端路由差异
platform: process.env.VUE_APP_PLATFORM,
// 小程序端路由配置:关闭跳转动画(默认300ms)
applet: {
animationDuration: 0
},
// 路由错误捕获与处理
routerErrorEach: ({ type, msg }) => {
switch (type) {
case 3: // 错误类型3:APP端触发退出应用逻辑
// #ifdef APP-PLUS // 仅在APP端执行
router.$lockStatus = false; // 解锁路由锁,避免后续跳转阻塞
uni.showModal({
title: '提示',
content: '您确定要退出应用吗?',
success: function(res) {
if (res.confirm) {
plus.runtime.quit(); // 执行APP退出操作
}
}
});
// #endif
break;
case 2: // 错误类型2:路由跳转失败(如页面不存在,已被404兜底)
case 0: // 错误类型0:未知基础错误
router.$lockStatus = false; // 解锁路由锁
break;
default: // 其他错误类型:仅解锁,不做额外处理
break;
}
},
// 路由表:合并业务路由 + 404通配符兜底路由
routes: [
...ROUTES, // 展开项目中定义的所有合法路由(如首页、我的钱包、商品页等)
{
path: '*', // 通配符:匹配所有未定义的路由路径
redirect: (to) => { // 重定向函数:to为目标非法路由信息
// 跳转到名称为"404"的页面(需在ROUTES中提前定义)
return {
name: '404'
}
}
}
]
});
/**
* 全局路由前置守卫:路由跳转前的拦截器
* @param {Object} to - 目标路由(要跳转到的页面)
* @param {Object} from - 来源路由(当前跳转前的页面)
* @param {Function} next - 放行/拦截函数:next()放行,next(false)拦截,next({path:''})重定向
*/
router.beforeEach((to, from, next) => {
// 1. 权限控制:判断目标页面是否需要登录(基于路由meta.auth字段)
// if (to.meta && to.meta.auth && !store.getters.isLogin) {
// // 未登录:触发登录弹窗,拦截路由跳转
// store.dispatch('showAuthModal'); // Vuex触发登录弹窗action
// next(false); // 阻止当前路由跳转
// }
// 2. 特定页面拦截:例如临时关闭充值页入口
// else if (to.path === '/pages/user/wallet/top-up') {
// next(false); // 拦截充值页跳转
// }
// 3. 合法路由:直接放行
// else {
next()
// }
});
// 导出路由实例和挂载方法,供main.js挂载使用
export {
router,
RouterMount
}
404 页面组件(pages/404/index.vue)
typescript
<template>
<!-- 404页面布局:友好提示 + 返回首页按钮 -->
<view class="page-404 flex flex-col justify-center items-center h-full">
<!-- 404提示文案 -->
<text class="text-404">页面走丢了 😵</text>
<text class="text-desc mt-2">您访问的页面不存在或已被删除</text>
<!-- 返回首页按钮 -->
<button class="btn-home mt-6" @click="goHome">返回首页</button>
</view>
</template>
<script>
export default {
name: 'page404',
methods: {
/**
* 返回首页逻辑:使用switchTab跳转(适配tabBar页面)
* 若首页非tabBar,改用uni.navigateTo/uni.redirectTo
*/
goHome() {
uni.switchTab({
url: '/pages/index/index',
fail: () => { // 跳转失败兜底(如首页非tabBar)
uni.redirectTo({
url: '/pages/index/index'
});
}
});
}
}
};
</script>
<style scoped>
/* 404页面样式:居中布局 + 友好样式 */
.page-404 {
background-color: #f5f5f5;
}
.text-404 {
font-size: 32rpx;
color: #333;
font-weight: bold;
}
.text-desc {
font-size: 28rpx;
color: #666;
}
.btn-home {
width: 200rpx;
height: 80rpx;
line-height: 80rpx;
background-color: #007aff;
color: #fff;
border-radius: 40rpx;
font-size: 28rpx;
}
</style>
main.js 中挂载路由
typescript
import { createSSRApp } from 'vue'
// 引入路由实例和挂载方法
import { router, RouterMount } from './router/index.js'
import store from './shopro/store'
import App from './App.vue'
export function createApp() {
const app = createSSRApp(App)
// 挂载Vuex仓库
app.use(store)
// 挂载路由实例
app.use(router)
// 仅H5端需要手动挂载(其他端由uni-simple-router自动处理)
// #ifdef H5
RouterMount(router, app, '#app')
// #endif
return {
app,
router
}
}