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()
相关推荐
局i25 分钟前
vue简介
前端·javascript·vue.js
yqcoder1 小时前
vue2 和 vue3 中,列表中的 key 值作用
前端·javascript·vue.js
梵得儿SHI1 小时前
Vue 指令系统:事件处理与表单绑定全解析,从入门到精通
前端·javascript·vue.js·v-model·v-on·表单数据绑定·表单双向绑定
lcc1871 小时前
Vue props
前端·vue.js
半开半落1 小时前
uniapp通过npm使用第三方库兼容微信小程序
微信小程序·npm·uni-app
秋天的一阵风2 小时前
😱一行代码引发的血案:展开运算符(...)竟让图表功能直接崩了!
前端·javascript·vue.js
Hilaku2 小时前
npm scripts的高级玩法:pre、post和--,你真的会用吗?
前端·javascript·vue.js
随笔记2 小时前
HbuilderX载入项目,运行后唤起微信开发者工具,提示:Error: Fail to open IDE,唤醒不起来怎么办
javascript·微信小程序·uni-app
Lsx_2 小时前
一文读懂 Uniapp 小程序登录流程
前端·微信小程序·uni-app
启山智软3 小时前
使用 Spring Boot + Vue.js 组合开发多商户商城(B2B2C平台)是一种高效的全栈技术方案
vue.js·spring boot·后端