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

Nuxt3点击下拉按钮获取子菜单API数据及状态显示问题求助

解决方案

你的问题核心在于useLazyFetch返回的data和pending是方法内部的局部变量,模板无法访问,同时缺少“仅请求一次”的限制逻辑。以下是修正后的完整代码,完全满足你的需求:

<template>
    <NuxtLink :to="url">
        {{ label }}
        <span @click.prevent="getChildren()">▾</span>
    </NuxtLink>

    <!-- Submenu -->
    <div v-if="isExpanded">
        <!-- 加载状态显示等待图标 -->
        <div v-if="pending">⏳ 加载中...</div>
        <!-- 渲染子菜单列表 -->
        <div v-else-if="subMenuItems.length">
            <div v-for="item in subMenuItems" :key="item.id">{{ item.label }}</div>
        </div>
        <!-- 无数据提示 -->
        <div v-else>暂无子菜单</div>
    </div>
</template>

<script setup>
const props = defineProps({
    label: String,
    url: String,
});

// 控制菜单展开/收起
const isExpanded = ref(false);
// 存储子菜单数据(模板可直接访问)
const subMenuItems = ref([]);
// 标记请求加载状态
const pending = ref(false);
// 标记是否已请求过数据,避免重复调用API
const hasFetched = ref(false);

const handleExpand = () => {
    isExpanded.value = !isExpanded.value;
};

const getChildren = async () => {
    handleExpand();
    // 已请求过数据则直接返回
    if (hasFetched.value) return;

    pending.value = true;
    try {
        // 发起API请求
        const { data } = await useLazyFetch('/api/items', {
            server: false,
        });
        // 将返回数据赋值给全局响应式变量
        subMenuItems.value = data.value || [];
    } catch (err) {
        console.error('获取子菜单失败:', err);
        subMenuItems.value = [];
    } finally {
        pending.value = false;
        hasFetched.value = true;
    }
};
</script>

关键修改说明:

  • 顶层声明响应式变量:把subMenuItems、pending、hasFetched放在<script setup>顶层,确保模板能直接访问这些变量。
  • 避免重复请求:用hasFetched标记是否已获取数据,点击按钮时先判断状态,已获取则不再调用API。
  • 手动维护加载状态:通过pending变量控制等待图标的显示,让用户清晰感知加载过程。
  • 异常处理:添加try/catch捕获请求错误,避免页面崩溃,同时保证数据状态的一致性。

如果你想直接使用Nuxt自带的请求状态管理,也可以简化成以下写法:

<script setup>
// ...其他变量不变
// 初始化时不自动发起请求
const { data: fetchedSubMenu, pending: fetchPending, refresh } = useLazyFetch('/api/items', {
    server: false,
    immediate: false,
});

const getChildren = async () => {
    handleExpand();
    if (hasFetched.value) return;
    // 手动触发请求
    await refresh();
    subMenuItems.value = fetchedSubMenu.value || [];
    hasFetched.value = true;
};
</script>

这种方式直接复用Nuxt返回的pending状态,无需手动维护加载变量,逻辑更简洁,可根据个人习惯选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 19:50:17