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
  }
}
相关推荐
局外人LZ1 天前
Uniapp脚手架项目搭建,uniapp+vue3+uView pro+vite+pinia+sass
前端·uni-app·sass
2501_915918411 天前
在 iOS 环境下查看 App 详细信息与文件目录
android·ios·小程序·https·uni-app·iphone·webview
前端呆头鹅1 天前
Websocket使用方案详解(uniapp版)
websocket·网络协议·uni-app
浮桥1 天前
uniapp+h5 公众号实现分享海报绘制
uni-app·notepad++
2501_916007471 天前
没有 Mac 用户如何上架 App Store,IPA生成、证书与描述文件管理、跨平台上传
android·macos·ios·小程序·uni-app·iphone·webview
wangjun51591 天前
uniapp uni.downloadFile 偶发性下载文件失败 无响应
uni-app
2501_915106322 天前
当 Perfdog 开始收费之后,我重新整理了一替代方案
android·ios·小程序·https·uni-app·iphone·webview
2501_915918412 天前
中小团队发布,跨平台 iOS 上架,证书、描述文件创建管理,测试分发一体化方案
android·ios·小程序·https·uni-app·iphone·webview
家里有只小肥猫2 天前
uniApp打包ios报错
ios·uni-app
jingling5552 天前
uniapp | 基于高德地图实现位置选择功能(安卓端)
android·前端·javascript·uni-app