uniapp开发app 实现简易的路由拦截器

在使用uni-app开发多端应用时,我们有时需要在路由跳转前执行一些操作。这种需求在浏览器中的方案已经很成熟了,Vue和React都有自己的路由管理工具,可以通过路由守卫实现,而在 uni-app开发原生应用时,可以借助 uni.addInterceptor 来模拟类似功能。

分享一个封装好的简易路由拦截器模块,支持统一拦截多个路由方法或单独拦截指定方法,并且支持拦截逻辑的自定义扩展。

🧩 使用场景

  • 页面跳转前确认是否保存更改
  • 用户未登录时禁止跳转到某些页面
  • 某些页面禁止后退操作
  • 记录页面跳转日志

📦 方法

封装后的模块 RouterInterceptor 提供以下两个主要方法:

  • init(callback):初始化全局拦截器,拦截 navigateToredirectTonavigateBackswitchTabreLaunch 五个常用方法。
  • initForMethod(method, callback):只拦截某个指定方法。

📄 源码解析

下面是完整的实现代码:

js 复制代码
/**
 * 简单的路由拦截器
 * 每次使用时实时创建拦截器
 * ps: 下面的$Log和$LogError是个人封装的log方法
 */

const RouterInterceptor = {
  init(callback) {
    if (typeof callback !== 'function') {
      $LogError('RouterInterceptor Init Error', '回调必须是函数')
      return { remove: () => {} }
    }

    const routeMethods = ['navigateTo', 'redirectTo', 'navigateBack', 'switchTab', 'reLaunch']

    routeMethods.forEach(method => {
      uni.addInterceptor(method, {
        invoke: args => {
          const pages = getCurrentPages()
          const currentPage = pages.length > 0 ? pages[pages.length - 1] : null
          const fromRoute = currentPage ? currentPage.route : ''
          const toUrl = method === 'navigateBack' ? (pages.length > 1 ? pages[pages.length - 2].route : '') : args.url || ''

          const result = callback(fromRoute, toUrl, method, args)

          if (result === false) {
            $Log('RouterInterceptor', `路由被拦截: ${method}`)
            return false
          }

          if (result && typeof result === 'object') {
            return result
          }

          return args
        }
      })
    })

    return {
      remove: () => {
        routeMethods.forEach(method => {
          uni.removeInterceptor(method)
        })
        $Log('RouterInterceptor', '所有拦截器已移除')
      }
    }
  },

  initForMethod(method, callback) {
    if (typeof callback !== 'function') {
      $LogError('', '回调必须是函数')
      return { remove: () => {} }
    }

    uni.addInterceptor(method, {
      invoke: args => {
        const result = callback(args)

        if (result === false) {
          $Log('RouterInterceptor', `路由被拦截: ${method}`)
          return false
        }

        if (result && typeof result === 'object') {
          return result
        }

        return args
      }
    })

    return {
      remove: () => {
        uni.removeInterceptor(method)
        $Log('RouterInterceptor', `${method} 拦截器已移除`)
      }
    }
  }
}

export default RouterInterceptor

🛠️ 使用示例

javascript 复制代码
js
复制编辑
const interceptor = RouterInterceptor.initForMethod('navigateBack', (args) => {
  const hasUnsavedChanges = true // 可从状态管理中获取

  if (hasUnsavedChanges) {
    uni.showModal({
      title: '提示',
      content: '你有未保存的修改,确定要离开吗?',
      success: res => {
        if (res.confirm) {
          uni.navigateBack(args)
        }
      }
    })

    return false
  }

  return args
})

2. 移除拦截器

csharp 复制代码
js
// 假设之前保存的返回值是 interceptor
interceptor.remove()
相关推荐
影子信息26 分钟前
vue 前端动态导入文件 import.meta.glob
前端·javascript·vue.js
青阳流月27 分钟前
1.vue权衡的艺术
前端·vue.js·开源
RunsenLIu29 分钟前
基于Vue.js + Node.js + MySQL实现的图书销售管理系统
vue.js·mysql·node.js
样子201831 分钟前
Vue3 之dialog弹框简单制作
前端·javascript·vue.js·前端框架·ecmascript
kevin_水滴石穿32 分钟前
Vue 中报错 TypeError: crypto$2.getRandomValues is not a function
前端·javascript·vue.js
翻滚吧键盘33 分钟前
vue文本插值
javascript·vue.js·ecmascript
华子w90892585934 分钟前
基于 SpringBoot+Vue.js+ElementUI 的 “花开富贵“ 花园管理系统设计与实现7000字论文
vue.js·spring boot·elementui
老家的回忆3 小时前
jsPDF和html2canvas生成pdf,组件用的elementplus,亲测30多页,20s实现
前端·vue.js·pdf·html2canvas·jspdf
牧杉-惊蛰3 小时前
uniapp微信小程序css中background-image失效问题
css·微信小程序·uni-app
hackchen4 小时前
从0到1解锁Element-Plus组件二次封装El-Dialog动态调用
前端·vue.js·elementui