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()
相关推荐
云水一下3 小时前
Vue.js从零到精通系列(二):响应式核心——ref、reactive、computed与watch
前端·javascript·vue.js
卤蛋fg64 小时前
vxe-table 列拖拽排序与行拖拽排序:让表格布局任意排序
vue.js
粉末的沉淀5 小时前
vue:Vite项目中高效管理纯色SVG图标的方案
前端·javascript·vue.js
卤蛋fg65 小时前
vxe-table 列宽与行高拖拽调整:让表格布局极其灵活,拖拽功能非常强大
vue.js
向日的葵0065 小时前
Vue 路由传参的三种方式(三)
vue.js·路由
如果超人不会飞6 小时前
TinyVue Checkbox复选框组件使用指南
前端·vue.js
如果超人不会飞6 小时前
TinyVue Radio单选框组件使用指南
vue.js
鲁班小子6 小时前
Vite resolve.dedupe 使用教程
vue.js·vite
如果超人不会飞6 小时前
TinyVue Input输入框组件使用指南
vue.js
如果超人不会飞6 小时前
TinyVue Pager分页组件使用指南
前端·vue.js