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

Nuxt3如何优雅暴露onMounted内useApi返回的状态变量

问题原因

你遇到的作用域错误本质是违反了Vue3组合式API的调用规则:将组合式函数useApi放在了onMounted的回调局部作用域内调用,解构得到的pending/data等变量自然无法被外部的组件上下文访问。
同时你封装的useApi底层返回的是Nuxt内置的useLazyFetch,本身就支持手动控制请求触发时机,完全不需要把整个调用逻辑塞进onMounted里。

最优实现方案

核心思路是:在setup顶层调用useApi拿到所有响应式返回值,关闭自动发起请求配置,等组件挂载完成后再手动触发请求,既解决作用域问题,又满足「挂载后才发请求」的时序要求。

1. 修正组件内调用逻辑

<script setup lang="ts">
// 顶层调用组合式函数,所有返回值天然在组件作用域可访问
// 传入immediate:false 关闭自动请求
const {
  data,
  refresh,
  pending,
  error
} = await useApi(`/profile/${$auth.user.profile.sid}`, {
  immediate: false
}, ['data']);

// 直接访问顶层的pending,不存在作用域问题
const computedWaiting = computed<boolean>(() => {
  return pending.value === true;
});

// 挂载完成后手动触发请求,完全符合时序要求
onMounted(() => {
  refresh()
});
</script>

2. 修正useApi的类型定义(可选但推荐)

你当前封装的useApi的options类型只引用了ohmyfetch原生的FetchOptions,没有包含Nuxt useFetch扩展的immediate/watch等配置项,会导致TS类型报错,调整下类型定义即可:

// 引入Nuxt的UseFetchOptions类型兼容扩展配置
import type { UseFetchOptions } from 'nuxt/app'
import { FetchOptions } from "ohmyfetch";

const csrf_cookie: string = "XSRF-TOKEN";

/**
 * 获取Sanctum需要的Cookie,浏览器自动处理
 */
export const useFetchCookies = async () => {
  await $fetch.raw("/backend/sanctum/csrf-cookie", {
    credentials: "include"
  });
};

/**
 * 封装通用Api请求方法
 */
export const useApi = async <T = any>(url: string, options?: UseFetchOptions<T>, pick?: any) => {
  let token = useCookie(csrf_cookie)?.value;

  if (!token) {
    await useFetchCookies();
    token = useCookie(csrf_cookie).value;
  }

  const headers: HeadersInit = {
    Accept: "application/json",
    "Cache-Control": "no-cache",
    "X-XSRF-TOKEN": token,
    ...options?.headers
  };

  const opts: UseFetchOptions<T> = options ? (({headers, ...opts}) => opts)(options) : null;

  return useLazyFetch<T>(`/backend/api${url}`, {
    server: false,
    credentials: "include",
    headers,
    ...opts,
    pick: pick
  });
};
不推荐的反模式说明

如果强行把useApi放在onMounted里,你需要手动在组件顶层声明所有对应的ref,在回调里做值同步:

// 冗余的顶层ref声明
const data = ref(null)
const pending = ref(false)
const error = ref(null)
const refresh = ref(() => {})

onMounted(async() => {
  const res = await useApi(`/profile/${$auth.user.profile.sid}`, null, ['data']);
  // 手动同步每一个返回值
  data.value = res.data.value
  pending.value = res.pending.value
  error.value = res.error.value
  refresh.value = res.refresh
});

const computedWaiting = computed<boolean>(() => {
  return pending.value === true;
});

这种写法会产生大量冗余代码,容易出现值同步遗漏、类型推导失效的问题,完全不符合组合式API的设计初衷。


内容的提问来源于stack exchange,提问作者SPQRInc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 02:33:27