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

 更新时间:2024年11月07日 11:35:33   作者:&白帝&  
useRouter 是 Vue 3 Composition API 中的钩子(hook),它只能在 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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue中push()和splice()的使用解析

    vue中push()和splice()的使用解析

    这篇文章主要介绍了vue中push()和splice()的使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • vue实现移动端可拖拽式icon图标

    vue实现移动端可拖拽式icon图标

    这篇文章主要为大家详细介绍了vue实现移动端可拖拽式icon图标,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Vue文件如何代替传统的HTML文件

    Vue文件如何代替传统的HTML文件

    随着前端工程化的不断推进,传统的HTML、CSS、JavaScript三者分离的开发模式逐渐显露出一些不足之处,尤其是在构建复杂的单页应用(SPA)时,Vue.js作为一个现代化的前端框架,提供了多种工具和技术来简化开发流程,本文将探讨.vue文件是如何替代传统HTML文件的角色
    2024-10-10
  • 如何实现vue的tree组件

    如何实现vue的tree组件

    这篇文章主要介绍了如何实现vue的tree组件,帮助大家更好的理解和学习vue框架,感兴趣的朋友可以了解下
    2020-12-12
  • Vue 源码分析之 Observer实现过程

    Vue 源码分析之 Observer实现过程

    这篇文章主要介绍了 Vue 源码分析之 Observer实现过程,Observer 最主要的作用就是实现了touch -Data(getter) - Collect as Dependency这段过程,也就是依赖收集的过程,感兴趣的朋友跟随脚本之家小编一起学习吧
    2018-03-03
  • 利用Vue实现一个markdown编辑器实例代码

    利用Vue实现一个markdown编辑器实例代码

    这篇文章主要给大家介绍了关于如何利用Vue实现一个markdown编辑器的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Vue具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-05-05
  • vue全局接入百度地图的实现示例

    vue全局接入百度地图的实现示例

    本文主要介绍了vue全局接入百度地图的实现示例,文中根据实例编码详细介绍的十分详尽,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • vue使用Highcharts实现不同高度的3D环形图

    vue使用Highcharts实现不同高度的3D环形图

    这篇文章主要为大家详细介绍了vue使用Highcharts实现不同高度的3D环形图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • 在Vue3中实现拖拽文件上传功能的过程详解

    在Vue3中实现拖拽文件上传功能的过程详解

    文件上传是我们在开发Web应用时经常遇到的功能之一,为了提升用户体验,我们可以利用HTML5的拖放API来实现拖拽文件上传的功能,本文将介绍如何在Vue3中实现这一功能,文中有详细的代码示例供大家参考,需要的朋友可以参考下
    2023-12-12
  • Vue 实现把表单form数据 转化成json格式的数据

    Vue 实现把表单form数据 转化成json格式的数据

    今天小编就为大家分享一篇Vue 实现把表单form数据 转化成json格式的数据,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-10-10

最新评论