Nuxt3重新请求服务器数据时子组件Props不更新问题排查
Nuxt3中useFetch请求数据后子组件不更新的问题解决
问题场景
使用最新版本Nuxt3开发时,遇到以下问题:异步请求服务器数据后存入响应式变量,通过props传递给子组件。首次请求正常,但重新请求数据时,父组件的响应式变量已被覆盖,子组件的数据却未更新,无任何变化。
父组件(Index.vue)代码
<script setup> import { API_KEY, BASE_URL } from "@/constants/index"; const city = ref("Paris"); const weatherInfo = ref(null); const getWeatherData = async () => { const { data } = await useFetch( `${BASE_URL}?q=${city.value}&appid=${API_KEY}` ); weatherInfo.value = data; }; </script> <template> <input @keyup.enter="getWeatherData" v-model="city" type="text" class="search" /> <TheWeatherSummary :weatherInfo="weatherInfo" /> </template>
子组件代码
<script setup> const props = defineProps({ weatherInfo: { type: [Object, null], required: true, }, }); </script> <template> {{ weatherInfo }} </template>
对比:原生fetch可正常工作
const getWeatherData = () => { fetch(`${BASE_URL}?q=${city.value}&appid=${API_KEY}`) .then(res => res.json()) .then(data => (weatherInfo.value = data)) }
问题原因
Nuxt3的useFetch返回的data是一个响应式ref对象,而非原始的请求数据。当你执行weatherInfo.value = data时,实际上是把这个ref对象本身赋值给了weatherInfo的value,而非ref内部存储的实际数据。
后续重新请求时,虽然data内部的value会更新,但weatherInfo.value指向的还是同一个ref对象,Vue的响应式系统无法检测到引用变化,因此子组件不会触发更新。
而原生fetch返回的是原始JSON对象,每次赋值都是新的对象引用,Vue能检测到这个变化,所以子组件可以正常更新。
解决方案
有两种可行的修改方式:
方式1:获取ref的原始值赋值
修改父组件的getWeatherData方法,将data.value(即ref内部的实际数据)赋值给weatherInfo.value:
const getWeatherData = async () => { const { data } = await useFetch( `${BASE_URL}?q=${city.value}&appid=${API_KEY}` ); // 赋值ref内部的原始数据,而非ref对象本身 weatherInfo.value = data.value; };
方式2:直接使用useFetch返回的响应式变量
不需要额外声明weatherInfo,直接使用useFetch返回的data,并通过refresh方法重新请求:
<script setup> import { API_KEY, BASE_URL } from "@/constants/index"; const city = ref("Paris"); // 直接解构获取响应式data和refresh方法 const { data: weatherInfo, refresh } = await useFetch( `${BASE_URL}?q=${city.value}&appid=${API_KEY}` ); const getWeatherData = async () => { // 调用refresh重新发起请求,自动更新data的值 await refresh(); }; </script> <template> <input @keyup.enter="getWeatherData" v-model="city" type="text" class="search" /> <TheWeatherSummary :weatherInfo="weatherInfo" /> </template>
两种方式都能确保父组件的响应式变量产生可被Vue检测到的变化,从而触发子组件的更新。
内容的提问来源于stack exchange,提问作者Alexander Derevkov
相关产品推荐
相关产品推荐

