TypeScript文件中用useRouter遇inject错误,401跳转问题如何解决
问题解决:
inject() can only be used inside setup() or functional components 问题根源
你在handleFetchError函数和ofetch的onRequest回调中直接调用了useRouter()和useCookie()——这两个都是Vue/Nuxt的组合式API函数,必须在Vue组件的setup()钩子、<script setup>或者函数组件内部才能调用。当前代码在普通工具函数和ofetch配置里调用它们,脱离了Vue的响应式上下文,导致触发inject()错误(useRouter内部依赖inject获取路由实例)。
最佳解决方案
把$api的创建逻辑移到Nuxt插件中,利用插件的上下文环境安全调用组合式API,再将$api注册为全局可用实例:
步骤1:创建Nuxt插件文件
在项目plugins目录下新建api.ts(或api.client.ts仅客户端运行):
import { ofetch } from 'ofetch' import type { Plugin } from '#app' export class CustomFetchError extends Error { public code: number public response?: Response constructor(code: number, message: string, response?: Response) { super(message) this.code = code this.name = 'CustomFetchError' this.response = response } } export default defineNuxtPlugin((nuxtApp) => { const router = useRouter() const HttpStatusCodesWasHandled = [401] // 替换为你实际需要处理的状态码数组 const handleFetchError = (response: Response) => { if (HttpStatusCodesWasHandled.includes(response.status)) { if (response.status === 401) { router.push('/auth') } throw new CustomFetchError(response.status, 'Error Was Handled', response) } else { throw new CustomFetchError(0, 'Error Not Handled', response) } } const $api = ofetch.create({ baseURL: import.meta.env.VITE_API_BASE_URL || '/api', timeout: 10000, async onRequest({ options }) { const accessToken = useCookie('accessToken').value if (accessToken) { options.headers = { ...options.headers, Authorization: `Bearer ${accessToken}`, } } }, async onResponse({ response }) { if (!response.ok) { handleFetchError(response) } }, async onResponseError({ response }) { if (!response.ok) { handleFetchError(response) } }, }) // 将$api注入全局,组件内可直接调用 nuxtApp.provide('api', $api) })
步骤2:组件/页面中使用$api
在Vue组件或页面中通过useNuxtApp获取实例:
const { $api } = useNuxtApp() // 示例请求 try { const userData = await $api('/user/profile') } catch (err) { // 自定义错误处理 }
替代方案(非插件方式)
如果不想用Nuxt插件,可在客户端环境用原生方式处理,但无法兼容服务端渲染:
// 修改handleFetchError的路由跳转逻辑 if (response.status === 401) { if (process.client) { window.location.href = '/auth' } } // 修改onRequest的cookie读取逻辑 async onRequest({ options }) { let accessToken = '' if (process.client) { accessToken = document.cookie.split('; ').find(row => row.startsWith('accessToken='))?.split('=')[1] || '' } if (accessToken) { options.headers = { ...options.headers, Authorization: `Bearer ${accessToken}`, } } },
优先推荐Nuxt插件方案,它能更好融入Nuxt生态,支持服务端渲染和上下文管理。
内容的提问来源于stack exchange,提问作者mohsen ahmadi
相关产品推荐
相关产品推荐

