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

NuxtLink与SSR疑问:返回父页时API调用为何变为客户端执行?

Nuxt SSR中API调用执行时机的疑问

项目场景

我用Nuxt JS开发SSR项目,页面结构如下:

/pages
  category
    [sub]
      index.vue
  index.vue

/pages/category/index.vue 代码

该页面调用API获取子分类列表并渲染NuxtLink:

<template>
    <div>
        <h1>Category</h1>
        <ul>
            <li v-for="subcategory in subcategories" :key="subcategory"><NuxtLink :to="'/category/' + subcategory">{{ subcategory }}</NuxtLink></li>
        </ul>
    </div>
</template>
<script setup>
// 返回 {'subcat1', 'subcat2'}
const { data: subcategories , error} = await useFetch('https:/myapi.com/subcategories', {
    headers : {Accept: 'application/json'},
    method: 'GET',
});
</script>

/pages/category/[sub]/index.vue 代码

该页面展示子分类名称,并提供返回/category的NuxtLink:

<template>
    <div>
        <h1>{{ subcategory }}</h1>
        <ul>
            <li><NuxtLink to="/category">Category</NuxtLink></li>
        </ul>
    </div>
</template>
<script setup>
const route = useRoute();
const subcategory = route.params.sub;
</script>

问题描述

首次访问/category时,API调用在服务端执行,能正常显示子分类。点击子分类进入/category/subcategory后,再点击返回/category的NuxtLink,此时API调用变为客户端执行。但把所有NuxtLink替换为a标签后,每次点击都会刷新页面,API调用始终在服务端执行。想理解为什么必须这么做才能让所有API调用都在服务端执行。


原因解析

这本质是Nuxt的客户端路由导航和全页面刷新的核心差异导致的:

  • NuxtLink的工作逻辑:
    NuxtLink是Nuxt专为SPA场景设计的路由组件,点击时通过Vue Router完成客户端路由切换,不会触发浏览器全页面刷新。此时页面的渲染逻辑(包括useFetch调用)只会在浏览器端执行——因为整个应用已经加载到客户端,服务端不会重新介入页面渲染流程。

  • a标签的工作逻辑:
    原生a标签会触发浏览器的全页面请求,每次点击都会向服务端发送新的页面请求。服务端会重新启动SSR流程,执行页面中的useFetch调用,渲染完整HTML后返回给浏览器,因此API调用始终在服务端执行。

优化方案(兼顾体验与服务端执行)

如果想保留无刷新跳转体验,同时让返回/category时API调用在服务端执行,无需替换为a标签,只需在NuxtLink中添加force: true属性即可强制触发服务端渲染:

<NuxtLink to="/category" :force="true">Category</NuxtLink>

或者通过navigateTo方法实现:

const goBackToCategory = () => navigateTo('/category', { force: true })

这样既能避免全页面刷新的体验损耗,又能确保API调用在服务端执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:02:30