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
  }
}
相关推荐
念你那丝微笑20 小时前
uView Plus + Vue3 + TypeScript + UniApp 正确引入 UnoCSS(避坑版)
vue.js·typescript·uni-app
念你那丝微笑21 小时前
vue3+ts在uniapp项目中实现自动导入 ref 和 reactive
vue.js·typescript·uni-app
游戏开发爱好者821 小时前
如何使用 AppUploader 提交上传 iOS 应用
android·ios·小程序·https·uni-app·iphone·webview
iOS阿玮2 天前
AppStore卡审依旧存在,预计下周将逐渐恢复常态!
uni-app·app·apple
郑州光合科技余经理2 天前
开发实战:海外版同城o2o生活服务平台核心模块设计
开发语言·git·python·架构·uni-app·生活·智慧城市
行走的陀螺仪2 天前
在UniApp H5中,实现路由栈的持久化
前端·javascript·uni-app·路由持久化·路由缓存策略
影子打怪2 天前
uniapp通过plus.geolocation.watchPosition获取的坐标格式转换
uni-app
忒可君2 天前
2026新年第一篇:uni-app + AI = 3分钟实现数据大屏
前端·vue.js·uni-app
行走的陀螺仪2 天前
UniApp 横向可滚动 Tab 组件开发详解
uni-app·封装组件·tabs·自定义封装组件·可滚动组件tab
00后程序员张2 天前
在 iPhone 上进行 iOS 网络抓包的实践经验
android·ios·小程序·https·uni-app·iphone·webview