NuxtLink与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

