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()
相关推荐
罚时大师月色1 天前
Vue+ts 如何实现父组件和子组件通信
javascript·vue.js·ecmascript
游戏开发爱好者81 天前
FTP 抓包分析实战,命令、被动主动模式要点、FTPS 与 SFTP 区别及真机取证流程
运维·服务器·网络·ios·小程序·uni-app·iphone
fury_1231 天前
vue3:数组的.includes方法怎么使用
前端·javascript·vue.js
宁&沉沦1 天前
Cursor 科技感的登录页面提示词
前端·javascript·vue.js
武天1 天前
如果使用Vue3.0实现一个 Modal,你会怎么进行设计?
vue.js
敲敲敲敲暴你脑袋1 天前
Canvas绘制自定义流动路径
vue.js·typescript·canvas
2501_915909061 天前
iOS 26 文件管理实战,多工具组合下的 App 数据访问与系统日志调试方案
android·ios·小程序·https·uni-app·iphone·webview
盛夏绽放1 天前
uni-app Vue 项目的规范目录结构全解
前端·vue.js·uni-app
国家不保护废物1 天前
Vue组件通信全攻略:从父子传到事件总线,玩转组件数据流!
前端·vue.js
写不来代码的草莓熊1 天前
vue前端面试题——记录一次面试当中遇到的题(9)
前端·javascript·vue.js