10

我正在 Nuxt 中使用 Apollo 获取一些数据。不知何故,当导航到该页面时,我收到一个错误

Cannot read property 'image' of undefined

当我刷新页面时,一切都按预期工作。

我发现一些人有类似的问题,但似乎没有解决方案对我有用:/

这是我现在的模板文件:

/products/_slug.vue

<template>
  <section class="container">
    <div class="top">
      <img :src="product.image.url"/>
      <h1>{{ product.name }}</h1>
    </div>
  </section>
</template>

<script>
import gql from 'graphql-tag'

export default {
  apollo: {
    product: {
      query: gql`
        query Product($slug: String!) {
          product(filter: { slug: { eq: $slug } }) {
            slug
            name
            image {
              url
            }
          }
        }
      `,
      prefetch({ route }) {
        return {
          slug: route.params.slug
        }
      },
      variables() {
        return {
          slug: this.$route.params.slug
        }
      }
    }
  }
}
</script>

除非我刷新页面,否则 $apolloData 基本上是空的。任何想法将不胜感激

编辑 又近了一步(我认为)。以前,第一次导航到页面时,所有内容(image.url 和名称)都是未定义的。

我补充说:

data() {
    return {
      product: []
    };
  }

在我的导出顶部,现在至少总是定义名称,所以如果我删除图像,一切都会按预期工作。只是 image.url 一直未定义。

我注意到的一件事(不确定有多相关)是这个问题只发生在使用 , 如果我使用普通的 a 标签它可以工作,但当然会带走 vue 的魔力。

EDIT-2 因此,如果我将 Nuxt 降级到 1.0.0 版本,一切正常

4

3 回答 3

8

我也偶然发现了这个问题,发现它隐藏在 Vue Apollo 文档中。

尽管与 OP 的回复非常相似,但似乎官方的方式是使用“$loadingKey”属性。

文档中的内容非常混乱,因为发生了很多事情。 https://vue-apollo.netlify.com/guide/apollo/queries.html#loading-state

<template>
  <main
    v-if="!loading"
    class="my-8 mb-4"
  >
    <div class="w-3/4 mx-auto mb-16">
      <h2 class="mx-auto text-4xl text-center heading-underline">
        {{ page.title }}
      </h2>
      <div
        class="content"
        v-html="page.content.html"
      ></div>
    </div>
  </main>
</template>
    
<script>
import { page } from "~/graphql/page";
    
export default {
  name: 'AboutPage',

  data: () => ({
    loading: 0
  }),
    
  apollo: {
    $loadingKey: 'loading',
    page: {
      query: page,
      variables: {
        slug: "about"
      }
    },
  }
}
</script>

如果您需要在 vue 中使用响应式属性,例如 slug,您可以使用以下方法进行操作。

<template>
  <main
    v-if="!loading"
    class="my-8 mb-4"
  >
    <div class="w-3/4 mx-auto mb-16">
      <h2 class="mx-auto text-4xl text-center heading-underline">
        {{ page.title }}
      </h2>
      <div
        class="content"
        v-html="page.content.html"
      ></div>
    </div>
  </main>
</template>
    
<script>
import { page } from "~/graphql/page";
    
export default {
  name: 'AboutPage',
    
  data: () => ({
    loading: 0
  }),
    
  apollo: {
    $loadingKey: 'loading',
    page: {
      query: page,
      variables() {
        return {
          slug: this.$route.params.slug
        }
      }
    },
  }
}
</script>
于 2020-02-01T12:44:25.257 回答
4

我认为这只是页面加载时间的问题。

如果您有多个产品,您应该迭代产品,或者v-if="product != null"在产品容器上有一个,只有在从 GraphQL 获取数据后才会呈现。

这样,您将仅在真正获取 HTML 时在 HTML 中使用该对象,并避免读取未定义的属性。

于 2019-03-19T10:32:16.533 回答
1

为了解决这个问题,你添加v-if="!$apollo.loading"到你打算在其中使用响应式道具的 HTML 容器中。

于 2021-04-29T21:51:22.027 回答