如何在Nuxt 3组件setup脚本外使用环境变量
解决Nuxt中组件外使用API_URL的问题
错误原因
你遇到的报错是因为useRuntimeConfig属于Nuxt专属的组合式函数,只能在Nuxt插件、钩子、中间件或Vue的setup函数中调用。直接在api.js的模块顶层调用useApiUrl,相当于脱离了Nuxt实例上下文,触发了限制检查。
可行解决方案:通过Nuxt插件初始化API配置
最稳妥的方式是借助Nuxt插件来获取runtimeConfig,再初始化你的HTTP实例,这样能确保配置在Nuxt上下文正确加载。
步骤1:重构api.js,改为可动态创建HTTP实例
将原来直接导出HTTP对象改为导出创建函数,让插件传入正确的API_URL:
// services/api.js export function createHttp(apiUrl) { return { baseURL: apiUrl, headers: { "Content-Type": "application/json", }, }; }
步骤2:创建Nuxt插件注入HTTP实例
在plugins目录下新建api.js,这里可以合法访问useRuntimeConfig,并将初始化后的HTTP实例注入到Nuxt应用:
// plugins/api.js import { createHttp } from "~/services/api"; export default defineNuxtPlugin((nuxtApp) => { const config = useRuntimeConfig(); const HTTP = createHttp(config.public.apiURL); // 将HTTP实例注入到应用,方便全局调用 return { provide: { http: HTTP } }; });
步骤3:修改Req类,接收HTTP实例
更新request.js,让Req类通过构造函数接收HTTP实例,避免直接依赖顶层的HTTP对象:
// services/request.js export default class Req { constructor(http) { this.http = http; // 初始化token逻辑 const token = localStorage.getItem("token"); if (token) { this.http.headers.Authorization = `JWT ${token}`; } else { delete this.http.headers.Authorization; } } async get(url, queryObject) { let runUrl = url; if (queryObject) { const queryParams = new URLSearchParams(); for (const key in queryObject) { if (Array.isArray(queryObject[key])) { queryObject[key].forEach(value => queryParams.append(key, value)); } else { queryParams.append(key, queryObject[key]); } } runUrl = `${url}?${queryParams.toString()}`; } try { const response = await fetch(`${this.http.baseURL}${runUrl}`, { method: "GET", headers: this.http.headers, }); if (!response.ok) throw new Error("Network response was not ok"); return await response.json(); } catch (error) { throw error; } } // post/put/patch/delete方法同理,将所有`HTTP`替换为`this.http` async post(url, payload) { try { const headers = { ...this.http.headers }; if (payload instanceof FormData) { delete headers["Content-Type"]; } else { headers["Content-Type"] = "application/json"; } const token = localStorage.getItem("token"); if (token) { headers["Authorization"] = `JWT ${token}`; } const response = await fetch(`${this.http.baseURL}${url}`, { method: "POST", headers: headers, body: payload instanceof FormData ? payload : JSON.stringify(payload), }); if (!response.ok) throw response; return await response.json(); } catch (error) { console.log(error); throw error; } } // 其他方法(put/patch/delete)按上述逻辑修改`HTTP`为`this.http` }
步骤4:在组件/页面中使用
在需要调用API的地方,通过useNuxtApp获取注入的HTTP实例,再初始化Req:
// 组件或页面中 const { $http } = useNuxtApp(); const req = new Req($http); // 调用示例 const data = await req.get("/users");
备选方案:服务端直接取环境变量(仅适用于服务端场景)
如果你的API调用只在服务端执行,也可以直接在api.js中通过环境变量获取:
// services/api.js export const HTTP = { baseURL: process.env.NUXT_PUBLIC_API_URL || "https://example-stage.herokuapp.com/v1/", headers: { "Content-Type": "application/json", }, };
注意:这种方式在客户端无法生效,因为客户端无法直接访问process.env.NUXT_PUBLIC_API_URL,必须通过useRuntimeConfig获取。
内容的提问来源于stack exchange,提问作者wale
相关产品推荐
相关产品推荐

