如何在使用 Nuxt 的 fetch() 挂钩获取数据时防止模板错误
Posted
技术标签:
【中文标题】如何在使用 Nuxt 的 fetch() 挂钩获取数据时防止模板错误【英文标题】:How to prevent template errors while fetching data with Nuxt's fetch() hook 【发布时间】:2021-08-23 10:08:56 【问题描述】:我正在尝试将我的 vue 应用程序转换为 nuxt 应用程序。在我的 vue 应用程序中,我轻松地使用了 vue-slick-corousel。但是对 nuxt 进行必要修改的相同代码,corousel 无法刷新。如果我实时编辑模板或在不刷新页面的情况下导航应用程序,它在第二次访问页面时可以完美运行。这是我在 nuxt 应用程序中使用 vue-slick-corousel 的方式
//nuxt.config.js
plugins: [
src: './plugins/vue-slick-carousel.js'
],
插件js文件中的代码:
//vue-slick-carousel.js
import Vue from 'vue'
import VueSlickCarousel from 'vue-slick-carousel'
Vue.component('VueSlickCarousel', VueSlickCarousel)
最后在模板中:
<!-- CustomComponent.vue -->
<template>
<div>
<VueSlickCarousel :arrows="true" :dots="true">
<div v-for="(cat, index) in categories"
:key="index"
style="height: 20px; width: 10px; background-color: red; color: white"
>
cat.name
</div>
</VueSlickCarousel>
</div>
</template>
<script>
import VueSlickCarousel from 'vue-slick-carousel'
import 'vue-slick-carousel/dist/vue-slick-carousel.css'
// optional style for arrows & dots
import 'vue-slick-carousel/dist/vue-slick-carousel-theme.css'
export default
name: 'CustomComponent',
data()
return
categories: []
,
async fetch()
this.categories = await fetch(
'https://*****************************/categories?limit=20'
).then(res => res.json())
,
components:
VueSlickCarousel
,
</script>
这是我在刷新时遇到的错误“TypeError: Cannot read property 'length' of undefined”
每当我从客户端再次渲染页面时,错误就会消失。已经尝试在
下绑定容器<client-only>
尝试使用条件
v-if="slik.length"
没用。我该如何解决这个问题?
【问题讨论】:
如何获取slik
?这个在某些时候是未定义的,因此length
的错误。这更像是一个生命周期问题。当然,它可以通过一些slik?.length
来解决,但这会更好地找出为什么会发生这种情况。
【参考方案1】:
编辑:这里是$fetchState.pending
helper 用法的解释。
fetch()
是一个非阻塞钩子,允许您在页面/组件加载时获取数据
asyncData()
会阻塞,但仅在您导航而不是在可能令人讨厌的初始渲染时
您可以使用fetch()
和a middleware
的组合进行阻止导航
使用skeletons 是一种让用户在感觉应用正在加载(Facebook-y)时等待的好方法
您的模板实际上是同步的,不会等待您收集数据,它希望立即拥有它。 VueSlickCarousel
实际上是在等你提供一组项目。但是在初始渲染和获取任何数据之前,您只有在data()
中设置categories: []
$fetchState.pending
是一个handy helper,它可以告诉我们fetch()
中的所有调用何时完成。因此,如果您将调用 4 个不同的 API,则只有当所有 4 个调用都完成时,它才会等于 false
。
您实际上也可以使用 this.$fetchState.pending = true
手动设置它,但这是强制的,应在正确理解时使用。
通过写<VueSlickCarousel v-if="!$fetchState.pending">
,我们基本上是在说等到我在fetch()
中的所有事情都完成后再安装这个组件。这可以防止出现任何 .length
方法问题,因为组件本身不会被挂载,直到有东西可以应用 .length
。
这是 Nuxt 生命周期的小图,重点关注 fetch()
钩子。
您不应混合使用 async/await
和 then
。尽量只使用其中一个(我推荐第一个)。
async fetch()
const response = await fetch(
'https://*****************************/categories?limit=20'
)
const fetchedCategories = await response.json()
console.log('categories', fetchedCategories)
this.categories = fetchedCategories
,
另外,:key="index"
是一种不好的做法,因为index
在v-for
中是可变的。尝试使用 API 中的 UUID。
我很确定这些都不是必需的:
import VueSlickCarousel from 'vue-slick-carousel'
components: VueSlickCarousel ,
【讨论】:
谢谢。会小心不使用 then 和 await 一起。但旋转木马仍然无法正常工作。它显示“TypeError:无法读取未定义的属性'长度'”。我想知道是否有任何方法可以在 s-s-r nuxt 中使用 vue-slick-carousel。正如他们在文档中所说的那样,它应该在 s-s-r 中完美运行 目前为止这和s-s-r无关。我没有尝试过这个特定的包,但看起来这仍然是早期没有填充数据的问题。试试这个<VueSlickCarousel v-if="!$fetchState.pending" :arrows="true" :dots="true">
。此外,控制台日志是否显示任何内容?
谢谢! if="!$fetchState.pending" 我认为实际上有效!虽然会做更多的测试和试验,但仍然没有错误。这很有帮助!你能解释一下这背后的逻辑吗?如果你把这个作为答案,我也可以打勾。再次,非常感谢!
当然。我一直在使用 fetch hook 来获取 nuxt 中的数据,不知道 fetch 也可以用这种方式在 slick carousel 中使用
最后,这只是您获取数据的方式/时间/地点的问题。尽管如此,Slick carousel 仍然可以完成它的工作,它只需要一个数组。以上是关于如何在使用 Nuxt 的 fetch() 挂钩获取数据时防止模板错误的主要内容,如果未能解决你的问题,请参考以下文章
如何在 useEffect 挂钩中使用 Promise.all 获取所有数据?