UniApp 路由配置实战:从全局守卫到 404 页面优雅处理

在 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
  }
}
相关推荐
5335ld3 小时前
uniapp-APP端table列表左侧第一列固定、头部固定
windows·uni-app
一个假的前端男3 小时前
uni-app App 端长按录音的工程级实现
uni-app
无名前端小白4 小时前
uniapp 安卓离线打包, 无法调起系统安装应用
uni-app
游戏开发爱好者84 小时前
苹果 App 上架流程,结合 Xcode、CI 等常见工具
macos·ios·ci/cd·小程序·uni-app·iphone·xcode
2501_915106324 小时前
用 HBuilder 上架 iOS 应用时如何管理Bundle ID、证书与描述文件
android·ios·小程序·https·uni-app·iphone·webview
2501_915909064 小时前
资源文件混淆在 iOS 应用安全中的实际价值
android·安全·ios·小程序·uni-app·iphone·webview
2501_915918414 小时前
iOS App 性能测试中常被忽略的运行期问题
android·ios·小程序·https·uni-app·iphone·webview
毕设源码-邱学长4 小时前
【开题答辩全过程】以 基于uni-app的装修现场管理小程序设计与实现为例,包含答辩的问题和答案
uni-app
郑州光合科技余经理6 小时前
PHP构建:支撑欧美澳市场的同城生活服务平台开发
java·开发语言·数据库·uni-app·php·排序算法·生活