浅析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 中。
2.在 Axios 中使用 router:
你可以在响应拦截器中访问存储的 router 实例,进而进行路由跳转。
示例实现:
在 store.js 或 Pinia 中存储 router 实例:
store.js (假设你使用 Pinia 或 Vuex 来管理全局状态)
在Pinia定义一个变量用来存储router
// 用来存储 router 实例 let router =ref(null)
在 App.vue 中将 router 存入 store:
在app.vue中给Pinia定义的变量赋值
import { useRouter } from 'vue-router' const router = useRouter() const appStore = getAppStore() appStore.router = router
修改 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');
2.在 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 直接暴露到全局中可以保持代码的模块化和清晰。
到此这篇关于浅析Vue3中useRouter怎么在Vue组件外使用的文章就介绍到这了,更多相关Vue3 useRouter内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
最新评论