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()
相关推荐
百锦再22 分钟前
# Vue + OpenLayers 完整项目开发指南
开发语言·前端·javascript·vue.js·python·ecmascript·tkinter
Jinxiansen021125 分钟前
Vue + Element Plus 实战:大文件切片上传 + 断点续传
前端·javascript·vue.js
Dignity_呱1 小时前
Vue性能优化:从加载提速到运行时优化
前端·vue.js·面试
【本人】1 小时前
Vue3中Axios的使用-附完整代码
vue.js·前端框架
架构个驾驾2 小时前
Vue2 与 Vuex 状态管理实战指南
前端·javascript·vue.js
Smile_frank2 小时前
vue-05(自定义事件)
vue.js
邹荣乐3 小时前
Vue事件总线(EventBus)使用指南:详细解析与实战应用
javascript·vue.js
七分小熊猫3 小时前
解决ios页面跳转后调用微信js-sdk签名认证失败
vue.js·微信
邹荣乐3 小时前
vue中内置指令v-model的作用和常见使用方法介绍以及在自定义组件上支持
前端·javascript·vue.js
前端工作日常3 小时前
我理解的Vue2单元测试之Jasmine
vue.js