nuxt3刷新代码执行,链接路由过来不执行的问题?

刚学Nuxt3项目,建了几个页面中间可以通过NuxtLink链接跳转,下面是一个页面,直接刷新useAsyncData相关的代码会执行,数据能拿到,但是通过其它页面跳转到这个页面时useAsyncData不执行,数据拿不到?这是为什么?useAsyncData代码需要放到生命周期里?

<template>
    <div class="mt-[80px] flex items-center justify-center">
        <div class="flex flex-col items-center">
            <div>新闻页面</div>
            <div>{{ route?.params.id }}</div>
            <div>{{ list }}</div>
        </div>
    </div>
</template>
<script setup lang="ts">
import { useAsyncData } from '#app';

const route = useRoute();
const list = ref();
const url = 'https://www.xxxxxx.com/api/'; //我执行时是正确的地址
const res = await useAsyncData('info', () => $fetch(url), { lazy: true });
list.value = res.data.value?.data;
onMounted(() => {
    console.log('xxxx');
});
</script>

<style scoped lang="less"></style>
阅读 1.9k
2 个回答

在 Nuxt 3 中,useAsyncData 是一个用于在组件外部(即在服务端或静态生成时)获取异步数据的 Composition API 函数。然而,你遇到的问题可能是由于对 useAsyncDatalazy 选项的误解。

问题分析

  1. lazy 选项的作用

    • lazy 设置为 true 时,useAsyncData 不会在组件首次加载时立即执行。相反,它会在组件实际需要这个数据的时候(通常是在某个特定的渲染或计算属性中被引用时)才执行。
    • 如果你的组件在渲染时没有直接引用 useAsyncData 返回的数据(或者这个引用是在某些条件下才发生的),那么数据可能不会被加载。
  2. 路由跳转与直接刷新的区别

    • 当你直接刷新页面时,Nuxt 会认为这是一个全新的页面加载,因此会执行所有相关的生命周期函数和异步数据获取。
    • 当你通过路由从其他页面跳转到这个页面时,如果组件没有卸载再重新加载(即只是替换了视图而不是整个页面刷新),并且 useAsyncData 被设置为 lazy,那么它可能不会立即执行,除非组件内部有某种方式触发了数据的加载。

解决方案

  1. 移除 lazy 选项

    • 如果你的数据是页面加载时就需要的,那么不应该使用 lazy 选项。去掉 lazy: true,这样 useAsyncData 就会在组件加载时立即执行。
  2. 确保数据被正确引用

    • 确保你的模板或其他计算属性中正确引用了 useAsyncData 返回的数据。如果数据没有被引用,即使去掉了 lazy 选项,useAsyncData 也可能不会执行。
  3. 使用 onMounted 生命周期钩子

    • 虽然 onMounted 钩子在客户端渲染时很有用,但它对于服务端渲染或静态生成并不起作用。因此,不应该依赖 onMounted 来触发 useAsyncData 的执行。相反,你应该让 useAsyncData 直接在组件加载时执行(即去掉 lazy 选项)。

修改后的代码可能如下:

<template>
    <div class="mt-[80px] flex items-center justify-center">
        <div class="flex flex-col items-center">
            <div>新闻页面</div>
            <div>{{ route?.params.id }}</div>
            <div v-if="res.data.value">{{ res.data.value.data }}</div>
            <div v-else>加载中...</div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { useAsyncData, useRoute } from '#app';

const route = useRoute();
const url = 'https://www.xxxxxx.com/api/'; // 确保这是正确的地址
const res = await useAsyncData('info', () => $fetch(url));
</script>

<style scoped lang="less"></style>

注意,我在模板中添加了 v-ifv-else 来处理数据加载中的状态。这样,当数据还没有加载完成时,用户会看到“加载中...”的提示。一旦数据加载完成,res.data.value 将包含你的数据,并且会被渲染到页面上。

可以通过监听路由变化来解决这个问题。将useAsyncData放在生命周期钩子中并不是最佳实践。可以使用watch来监听路由参数的变化,并在变化时重新调用useAsyncData。

<template>
    <div class="mt-[80px] flex items-center justify-center">
        <div class="flex flex-col items-center">
            <div>新闻页面</div>
            <div>{{ route?.params.id }}</div>
            <div>{{ list }}</div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { useAsyncData } from '#app';
import { ref, watch } from 'vue';
import { useRoute } from 'vue-router';

const route = useRoute();
const list = ref();
const url = 'https://www.xxxxxx.com/api/'; // 确保这是正确的地址

const fetchData = async () => {
    const res = await useAsyncData('info', () => $fetch(url));
    list.value = res.data.value?.data;
};

// 初始加载数据
fetchData();

// 监听路由参数变化
watch(() => route.params.id, () => {
    fetchData();
});

onMounted(() => {
    console.log('xxxx');
});
</script>

<style scoped lang="less"></style>

这样,每当路由参数变化时,fetchData函数都会被调用,从而重新获取数据。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏