如何在使用 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 手动设置它,但这是强制的,应在正确理解时使用。 通过写&lt;VueSlickCarousel v-if="!$fetchState.pending"&gt;,我们基本上是在说等到我在fetch() 中的所有事情都完成后再安装这个组件。这可以防止出现任何 .length 方法问题,因为组件本身不会被挂载,直到有东西可以应用 .length

这是 Nuxt 生命周期的小图,重点关注 fetch() 钩子。


您不应混合使用 async/awaitthen。尽量只使用其中一个(我推荐第一个)。

async fetch() 
  const response = await fetch(
    'https://*****************************/categories?limit=20'
  )
  const fetchedCategories = await response.json()
  console.log('categories', fetchedCategories)
  this.categories = fetchedCategories
,

另外,:key="index" 是一种不好的做法,因为indexv-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无关。我没有尝试过这个特定的包,但看起来这仍然是早期没有填充数据的问题。试试这个&lt;VueSlickCarousel v-if="!$fetchState.pending" :arrows="true" :dots="true"&gt;。此外,控制台日志是否显示任何内容? 谢谢! if="!$fetchState.pending" 我认为实际上有效!虽然会做更多的测试和试验,但仍然没有错误。这很有帮助!你能解释一下这背后的逻辑吗?如果你把这个作为答案,我也可以打勾。再次,非常感谢! 当然。我一直在使用 fetch hook 来获取 nuxt 中的数据,不知道 fetch 也可以用这种方式在 slick carousel 中使用 最后,这只是您获取数据的方式/时间/地点的问题。尽管如此,Slick carousel 仍然可以完成它的工作,它只需要一个数组。

以上是关于如何在使用 Nuxt 的 fetch() 挂钩获取数据时防止模板错误的主要内容,如果未能解决你的问题,请参考以下文章

如何在 useEffect 挂钩中使用 Promise.all 获取所有数据?

Vue / Nuxt.js - 在创建的钩子中调用两次 API

一起使用 fetch 和 asyncData

如何根据 API 获取的内容创建列表 + 详细信息页面

React内部useEffect中使用fetch的问题

使用 react 定期运行 fetch