You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 02:47:08