当前位置: 首页 > article >正文

Vue3中useRouter 怎么在Vue 组件外使用

useRouter 是 Vue 3 Composition API 中的钩子(hook),它只能在 Vue 组件中使用,而不是在普通的 JavaScript 模块或工具函数中。

为了在拦截器中使用 router,你需要在 Axios 响应拦截器中获取到 router 实例。你可以通过以下两种方式来解决这个问题:

方案 1:将 router 作为参数传递到拦截器中

一种常见的解决方案是在设置 Axios 实例时,把 router 作为参数传递给需要使用它的地方。你可以通过 Vue 的全局状态(比如 Vuex 或 Pinia)来存储 router 实例,然后在拦截器中使用它。

步骤:

  1. 在主应用中传递 router:

你可以在你的 Vue 应用的主组件(比如 App.vue)中获取 router 实例并将其存储在 Vuex 或 Pinia 中。

  1. 在 Axios 中使用 router:

你可以在响应拦截器中访问存储的 router 实例,进而进行路由跳转。

示例实现:

  1. 在 store.js 或 Pinia 中存储 router 实例:

// store.js (假设你使用 Pinia 或 Vuex 来管理全局状态)
在Pinia定义一个变量用来存储router

// 用来存储 router 实例
  let router  =ref(null)
  1. 在 App.vue 中将 router 存入 store:
    在app.vue中给Pinia定义的变量赋值
import { useRouter } from 'vue-router'
const router = useRouter()

const appStore = getAppStore()
appStore.router = router
  1. 修改 Axios 配置文件,使用存储的 router 实例:
import axios from 'axios'
import { getAppStore } from '../store'
import { showDialog } from 'vant'
import { useRouter } from 'vue-router';
const router = useRouter()

const sender = axios.create({
  baseURL: import.meta.env.PROD ? import.meta.env.VITE_API_TARGET : 'api',
  headers: {
    'Content-Type': 'application/json'
  }
});

const appStore = getAppStore()
// const router = useRouter()
// 添加请求拦截器
// https://axios-http.com/zh/docs/interceptors
sender.interceptors.request.use(function (config) {
  // console.log('请求拦截器')
  // 统一添加 token 请求头
  config.headers['Authorization'] = appStore.token
  return config;
}, function (error) {
  // console.log('请求拦截器 error: ', error)
  // 对请求错误做些什么
  return Promise.reject(error);
});

// 添加响应拦截器
sender.interceptors.response.use(function (response) {
  // console.log('响应拦截器', response)
  // 2xx 范围内的状态码都会触发该函数。
  // 对响应数据做点什么
  appStore.loading = false
  if (response.headers.token) {
    appStore.token = response.headers.token
    // console.log('update token '+response.headers.token)
  }

  return response.data
}, function (error) {
  // console.log('响应拦截器 error: ', error)
  // 超出 2xx 范围的状态码都会触发该函数。
  // 对响应错误做点什么
  appStore.loading = false
  if (error.status === 401) {
    appStore.isLogin = false
    appStore.token = ''
    const router = appStore.router;
    router.push('/login')
  }

  if (error.status === 422) {
    showDialog({
      teleport: '#main',
      className: 'global-dialog',
      showConfirmButton: false,
      closeOnClickOverlay: true,
      message: error.response.data.message
    })
  }
  return Promise.reject(error)
});

export const send = sender

方案 2:通过 window 或 global 暴露 router

如果你不想使用全局状态管理,也可以通过全局对象(如 window)来暂时存储 router 实例。这样做虽然不太推荐,但也能实现需求。

示例实现:

  1. 在 App.vue 中将 router 暴露到 window 上:
// App.vue
import { createApp } from 'vue';
import App from './App.vue';
import { createRouter } from 'vue-router';
import { routes } from './router';

const router = createRouter({
  history: createWebHistory(),
  routes,
});

// 暴露 router 实例到 window 对象
window.appRouter = router;

const app = createApp(App);
app.use(router).mount('#app');
  1. 在 Axios 配置中直接使用 window.appRouter:
// axios.js
import axios from 'axios';
import { showDialog } from 'vant';

const sender = axios.create({
  baseURL: import.meta.env.PROD ? import.meta.env.VITE_API_TARGET : 'api',
  headers: {
    'Content-Type': 'application/json',
  },
});

// 添加请求拦截器
sender.interceptors.request.use(function (config) {
  // ...请求拦截逻辑
  return config;
}, function (error) {
  return Promise.reject(error);
});

// 添加响应拦截器
sender.interceptors.response.use(function (response) {
  // ...响应拦截逻辑
  return response.data;
}, function (error) {
  // 使用 window.appRouter 进行路由跳转
  if (error.status === 422) {
    const router = window.appRouter;
    if (router) {
      router.push('/login');
      showDialog({
        teleport: '#main',
        className: 'global-dialog',
        showConfirmButton: false,
        closeOnClickOverlay: true,
        message: error.response.data.message,
      });
    }
  }

  return Promise.reject(error);
});

export const send = sender;

总结
最好的方法是通过全局状态管理(如 Pinia 或 Vuex)来存储 router 实例,这样可以确保 router 的实例在任何需要使用它的地方都能正确获取,而不必依赖 window 或全局对象。此外,避免将 router 直接暴露到全局中可以保持代码的模块化和清晰。


http://www.kler.cn/a/383956.html

相关文章:

  • 并查集(基础学习与应用)
  • ubuntu中安装mysql
  • SpringBoot3集成Junit5
  • DataX 的安装配置和使用 (详细版)
  • 新160个crackme - 093-kesan
  • 高清烟花视频素材下载网站推荐
  • [OS]vma? trap? Sys_mmap根据思路来实现!!
  • 2.3立项【硬件产品立项的核心内容】
  • UI界面设计入门:打造卓越用户体验
  • CAN通信协议 HAL库学习
  • 【数据集】【YOLO】【目标检测】安全帽识别数据集 22789 张,YOLO安全帽佩戴目标检测实战训练教程!
  • 【芯智雲城】Sigmastar星宸科技图传编/解码方案
  • springboot图书管理系统(一个简单的单体架构项目,适合小白)
  • JAVA 通过三菱MC协议 采集设备寄存器地址信息
  • 王珊数据库系统概论第六版PDF+第五版课后答案+课件
  • Android 开发 Java中 list实现 按照时间格式 yyyy-MM-dd HH:mm 顺序
  • aspose如何获取PPT放映页“切换”的“持续时间”值
  • 基础数据结构——队列(链表实现)
  • 【django】Django REST Framework (DRF) 项目中实现 JWT
  • Caused by: org.apache.flink.api.common.io.ParseException: Row too short:
  • Java实现pdf转图片
  • ipv6的 fc00(FC00::/7) 和 fec0(FEC0::/10)
  • 深度学习:Masked Self-Attention 详解
  • 【Chapter 2_ Sentosa_DSML Community Edition Product Features】
  • 职场浅谈:情商高的“4”种表现,情商高的人才更容易走向成功
  • yolo v5 开源项目