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
  }
}
相关推荐
Mintopia12 小时前
uni-app x 发展前景技术分析:跨端统一的新阶段?
uni-app
不爱说话郭德纲1 天前
告别漫长的HbuilderX云打包排队!uni-app x 安卓本地打包保姆级教程(附白屏、包体积过大排坑指南)
android·前端·uni-app
HashTang3 天前
【AI 编程实战】第 12 篇:从 0 到 1 的回顾 - 项目总结与 AI 协作心得
前端·uni-app·ai编程
JunjunZ3 天前
uniapp 文件预览:从文件流到多格式预览的完整实现
前端·uni-app
郑州光合科技余经理3 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
TT_Close3 天前
“啪啪啪”三下键盘,极速拉起你的 uni-app 项目!
vue.js·uni-app·前端工程化
特立独行的猫a4 天前
uni-app x跨平台开发实战:开发鸿蒙HarmonyOS影视票房榜组件完整实现过程
华为·uni-app·harmonyos·轮播图·uniapp-x
00后整顿职场4 天前
Hbuilderx APP真机无法识别iqoo Z9+手机设备解决方案
uni-app·uniapp真机调试·真机运行
前端小雪的博客.4 天前
【保姆级教程】uniAI 插件高效开发 uni-app 微信小程序(附实战案例)
微信小程序·uni-app·ai编程·uniai
T^T尚4 天前
一个完整的项目怎么打包成为一个app
前端·uni-app