Nuxt 3动态页面更改Url但不更改内容并且仅获取数据一次

spo*_*802 2 vue.js nuxt.js vuejs3 nuxtjs3

我有一个products/index页面,products/[slug]在主产品页面中,我有一个NuxtLink更改页面并转到products/[slug]并获取该产品的数据。

\n

第一次单击时,我有正确的数据,但是当我单击后退或单击产品/索引页面然后尝试单击另一个产品时,我有我单击的第一个产品的信息,并且在每个产品上,我再次有我点击的第一个产品的信息。

\n

使用console.log引导我发现我的获取数据没有改变,我在这里错过了什么吗?

\n

使用:keyand :page-keyon<nuxtPage/>不起作用。

\n

我点击的第一个产品

\n

我点击的第一个产品

\n

第二个产品仍然没有变化,数据来自第一个产品

\n

第二个产品仍然没有变化,数据来自第一个产品

\n

第三张图还是没有变化

\n

第三张图片仍然没有变化

\n

productComponent.vue

\n
<template>\n  <div class="mx-auto rounded border mb-7 border-blue-200 pt-1 px-2 mx-1 mb-2">\n    <NuxtLink :to="link">\n      <img\n        class="rounded mx-auto mb-3 border-b border-y-blue-300 pb-3"\n        :src="img"\n        :alt="alt"\n      />\n      <div class="mt-2">\n        <div>\n          <div class="items-center font-bold text-slate-700 leading-snug">\n            <p class="pr-3">{{ title }}</p>\n          </div>\n          <div class="mt-2 text-lg text-slate-600 pr-3 pb-2">\n            \xd9\x82\xdb\x8c\xd9\x85\xd8\xaa : {{ price }} \xd8\xaa\xd9\x88\xd9\x85\xd8\xa7\xd9\x86\n          </div>\n        </div>\n      </div>\n    </NuxtLink>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: \'ProductComponent\',\n  props: [\'title\', \'price\', \'img\', \'alt\', \'link\'],\n}\n</script>\n
Run Code Online (Sandbox Code Playgroud)\n

products/index.vue

\n
<script setup>\nuseHead({\n  title: \'\xd9\x85\xd8\xad\xd8\xb5\xd9\x88\xd9\x84\xd8\xa7\xd8\xaa\',\n})\nconst {data, pending, refresh, error} = await useFetch(\'http://127.0.0.1:8000/api/products\')\nconst products=data._value.data.data\n</script>\n<template>\n  <div>\n    <main  class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">\n      <div class="relative z-10 flex items-baseline justify-between pt-24 pb-6 border-b mb-7 border-gray-200">\n        <h1 class="text-4xl font-extrabold tracking-tight ">\xd9\x85\xd8\xad\xd8\xb5\xd9\x88\xd9\x84\xd8\xa7\xd8\xaa</h1>\n      </div>\n      <div class=" border border-blue-300 mx-auto p-4 mb-7">\n        <div class="grid sm:grid-cols-2 md:grid-cols-2 gap-2 lg:grid-cols-3 xl:grid-cols-4">\n          <div v-for="(product,index) in products" :key="index">\n            <product-component :title="product.name"\n                               :price="product.price"\n                               :img="\'http://127.0.0.1:8000/\'+product.image[0].indexArray.large"\n                               :alt="product.name"\n                               :link="\'/products/\'+product.slug">\n            </product-component>\n          </div>\n        </div>\n      </div>\n    </main>\n  </div>\n</template>\n
Run Code Online (Sandbox Code Playgroud)\n

products/[slug]

\n
<script setup>\nconst route = useRoute();\nconst {data: productData, pending, refresh, error} = await useFetch(`http://127.0.0.1:8000/api/products/${route.params.slug}`)\nconst product = productData._value.data[0]\nconsole.log(product)\n</script>\n<template>\n  <div class="container mx-auto">\n    <section class="grid grid-cols-12 gap-3 mb-7 ">\n      <!--      little pic-->\n      <div class="md:col-span-1 mx-auto md:flex md:flex-wrap hidden overflow-auto" style="max-height: 36rem">\n        <div class="cursor-pointer bg-amber-100 max-h-9">\n          <div class="max-h-fit mb-3 " v-for="(myImage , index) in product.image" :key="index"\n               @click="switchImage(\'http://127.0.0.1:8000/\'+myImage.indexArray.large)">\n            <img class="object-fill " style="width: 80px;height: 60px"\n                 :src="\'http://127.0.0.1:8000/\'+myImage.indexArray.large"\n                 :alt="myImage.alt">\n          </div>\n        </div>\n      </div>\n      <!--      end of little pic-->\n      <!--      pic-->\n      <div v-if="image" class="md:col-span-6 col-span-12 w-100 w-full max-w-full">\n        <img class=""\n             :src="image"\n             :alt="image.alt">\n      </div>\n      <div v-else class="md:col-span-6 col-span-12 ">\n        <img class="object-fill"\n             :src="\'http://127.0.0.1:8000/\'+product.image[0].indexArray.large"\n             alt="">\n      </div>\n      <!--end of pic-->\n      <div class="col-span-12 md:hidden">\n        <div class="cursor-pointer overflow-x-scroll">\n          <div class=" mb-3 inline py-1 " v-for="(myImage , index) in product.image" :key="index" @click="switchImage(index)">\n            <img class="object-fill inline p-1 overflow-x-scroll" style="width: 80px;height: 60px"\n                 :src="myImage.url"\n                 :alt="myImage.alt">\n          </div>\n        </div>\n      </div>\n      <!--      details-->\n      <div class="col-span-12 md:col-span-4">\n        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">\n          <p> \xd9\x86\xd8\xa7\xd9\x85 \xd9\x85\xd8\xad\xd8\xb5\xd9\x88\xd9\x84 :</p>\n          <p>{{ product.name }}</p>\n        </div>\n        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">\n          <p> \xda\xa9\xd8\xb4\xd9\x88\xd8\xb1 :</p>\n          <p>{{ product.country }}</p>\n        </div>\n        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">\n          <p> \xd8\xac\xd9\x86\xd8\xb3 :</p>\n          <p>{{ product.material }}</p>\n        </div>\n        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">\n          <p> \xd8\xb3\xd9\x86 :</p>\n          <p>{{ product.age }}</p>\n        </div>\n        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">\n          <p> \xd8\xb1\xd9\x86\xda\xaf :</p>\n          <p>{{ product.color }}</p>\n        </div>\n        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">\n          <p> \xd9\x88\xd8\xb2\xd9\x86 :</p>\n          <p>{{ product.weight }}</p>\n        </div>\n        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">\n          <p> \xd8\xb7\xd9\x88\xd9\x84 :</p>\n          <p>{{ product.length }}</p>\n        </div>\n        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">\n          <p> \xd8\xb9\xd8\xb1\xd8\xb6 :</p>\n          <p>{{ product.width }}</p>\n        </div>\n        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">\n          <p> \xd8\xa7\xd8\xb1\xd8\xaa\xd9\x81\xd8\xa7\xd8\xb9 :</p>\n          <p>{{ product.height }}</p>\n        </div>\n        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">\n          <p> \xd9\x82\xdb\x8c\xd9\x85\xd8\xaa :</p>\n          <p>{{ product.price }}</p>\n        </div>\n      </div>\n      <!--      end of details-->\n    </section>\n\n    <div class="p-3 mb-7" style="background-color:beige;">\n      <ul class="flex flex-row md:space-x-6">\n        <li class="block py-2 pr-4 pl-3 text-black">\n          \xd8\xaa\xd9\x88\xd8\xb6\xdb\x8c\xd8\xad\xd8\xa7\xd8\xaa\n        </li>\n      </ul>\n    </div>\n    <div class="mb-5 mx-auto whitespace-normal p-1 border-b border-amber-100-200 ">\n      <div v-html="product.description"></div>\n    </div>\n    <div class="mb-7">\n      <span class="block mb-4"> \xd8\xa8\xd8\xb1\xda\x86\xd8\xb3\xd8\xa8 \xd9\x87\xd8\xa7 : </span>\n      <a v-for="(tags , index) in product.tags.split(\',\')" :title="tags" :key="index"\n         class="rounded-md text-sm" style="margin: 3px" rel="tag"\n         href="">{{ tags }} / </a>\n    </div>\n  </div>\n</template>\n\n\n<script>\nexport default {\n  data() {\n    return {\n      image: null,\n    }\n  },\n  methods: {\n    switchImage(index) {\n      this.image = index;\n    },\n  },\n}\n</script>\n
Run Code Online (Sandbox Code Playgroud)\n

spo*_*802 8

我找到了解决方案,我必须在 useFetch 中添加一个参数

const {data: productData, pending, refresh, error} = await useFetch(`http://127.0.0.1:8000/api/products/${slug}` , { initialCache: false })
Run Code Online (Sandbox Code Playgroud)

因为 api 缓存并且不会发送另一个请求,所以initialCache : false 它会发送另一个请求,这种方式对于主要产品很有用,但在 products/[slug] 或 blog/[slug] 中,我认为如果您有的话,您必须为我做这种评论请有更好的方法

  • 您可以将密钥传递给 useFetch。与 initalCache: false 相比的优点是数据不会被多次获取。这可能会有所帮助:https://v3.nuxtjs.org/api/composables/use-fetch#params (2认同)