Vue apollo 将结果添加到数组

Posted

技术标签:

【中文标题】Vue apollo 将结果添加到数组【英文标题】:Vue apollo add results to array 【发布时间】:2021-10-03 12:46:45 【问题描述】:

这可能只是一个基本的 vue 问题,但我使用的是 Vue Apollo。 我有这样设置的组件:

export default defineComponent(
  name: "Products",
  components:  Product ,
  props: 
    categorySlug: 
      type: String,
      required: true,
    ,
  ,
  setup(props) 
    const  categorySlug  = toRefs(props);
    const page = ref(1);
    const skip = ref(0);
    const result = reactive( search: null, laoding: null, error: null );

    Object.assign(result, useListProducts(categorySlug.value, page.value));

    const more = () => 
      skip.value += 12;
      page.value += 1;

      Object.assign(result, useListProducts(categorySlug.value, page.value));
    ;

    return  ...toRefs(result), ... skip, more  ;
  ,
);

如您所见,我有一个反应式对象设置,它在调用组件设置方法时被分配:

const result = reactive( search: null, laoding: null, error: null );

Object.assign(result, useListProducts(categorySlug.value, page.value));

在我的模板中,我像这样迭代结果:

<base-fade-up class="row" :duration="0.1" tag="div">
  <v-col
    cols="12"
    xl="2"
    v-for="(product, index) in products"
    :key="product.id"
    :data-index="index"
    :data-skip="skip"
  >
    <product class="product" :product="product"></product>
  </v-col>
</base-fade-up>

我的问题是我想添加一个更多按钮:

<v-btn color="primary" @click="more()" v-if="search.hasMoreResults"
  >Show more</v-btn
>

按下时,它会执行 more() 方法:

const more = () => 
  skip.value += 12;
  page.value += 1;

  Object.assign(result, useListProducts(categorySlug.value, page.value));
;

如您所见,我现在获得了 第 2 页,因此第 1 页的产品不再位于 search 对象中。 我想做的是从第一个查询中获取产品的副本,然后在每次按下更多按钮时添加到它们。 我试过这个:

setup(props) 
  const  categorySlug  = toRefs(props);
  const page = ref(1);
  const skip = ref(0);
  const products = ref([]);
  const result = reactive( search: null, laoding: null, error: null );

  Object.assign(result, useListProducts(categorySlug.value, page.value));

  const more = () => 
    skip.value += 12;
    page.value += 1;

    Object.assign(result, useListProducts(categorySlug.value, page.value));
  ;

  products.value.push(result.search.value.items);

  return  ...toRefs(result), ... products, skip, more  ;
,

但是当我运行这段代码时,我得到一个错误:

[Vue 警告]:data() 中的错误:“TypeError: Cannot read property 'value' of null”

在这一行抱怨result.search.value

products.value.push(result.search.value.items);

我相信这是因为承诺尚未解决。 我在 useListProducts 中使用了 Apollo 的 useResult 方法,如下所示:

import  useQuery, useResult  from "@vue/apollo-composable";
import * as listProducts from "@/graphql/api/query.products.gql";

export function useListProducts(slug: string, page = 1, itemsToShow = 12) 
  const request: 
    identifier?: string;
    searchTerm: string;
    itemsToShow: number;
    page: number;
    filters: any;
    facets: string[];
   = 
    searchTerm: "*",
    itemsToShow,
    page,
    filters: [
      
        key: "CategorySlug",
        value: `'$slug'`,
      ,
    ],
    facets: ["Criteria/Attribute,count:100"],
  ;

  const  result, loading, error  = useQuery(listProducts, 
    search: request,
  );
  const search = useResult(result, null, (data) => data.search);
  return  search, loading, error ;

谁能告诉我我做错了什么?

【问题讨论】:

它需要仔细查看,但您不应该访问在 setup 正文中初始化时不可用的内容,除非它使用悬念。钩子(使用...)应该只出现在setup,而不是moreproducts.value.push(result.search.value.items) 属于 watch 或 watchEffect ,需要检查它们是否可用于条件语句。 const result = ... Object.assign(result ... - 这没有意义,useListProducts 已经返回了一个对象,分配给result 并没有好处,这不会使它更具反应性。 感谢您的回复。我是 vue 新手,所以虽然我很欣赏你的帖子,但它对我一点帮助都没有:( 【参考方案1】:

经过一番挖掘,我在文档中发现了一些关于分页的内容(这基本上就是我正在做的事情),因此我设法将我的代码调整为:

export default defineComponent(
  name: "Products",
  components:  Product ,
  props: 
    categorySlug: 
      type: String,
      required: true,
    ,
  ,
  setup(props) 
    const  categorySlug  = toRefs(props);
    const page = ref(1);
    const skip = ref(0);
    const  search, loading, error, fetchMore  = useListProducts(
      categorySlug.value,
      page.value
    );

    const more = () => 
      skip.value += 12;
      page.value += 1;

      const request = 
        ...params,
        ...
          page: page.value,
          filters: [
            
              key: "CategorySlug",
              value: `'$categorySlug.value'`,
            ,
          ],
        ,
      ;
      fetchMore(
        variables:  search: request ,
        updateQuery: (prev,  fetchMoreResult ) => 
          if (!fetchMoreResult) return prev;
          //return fetchMoreResult;
          console.log(fetchMoreResult);
          return Object.assign(, prev, 
            search: 
              hasMoreResults: fetchMoreResult.search.hasMoreResults,
              total: fetchMoreResult.search.total,
              facets: [...prev.search.facets, ...fetchMoreResult.search.facets],
              items: [...prev.search.items, ...fetchMoreResult.search.items],
              __typename: prev["__typename"],
            ,
          );
        ,
      );
    ;

    return  search, loading, error, skip, more ;
  ,
);

这满足了 Estus 在 cmets 中提到的所有内容,但确实会引发错误,我将创建一个关于该问题的新帖子:D

【讨论】:

以上是关于Vue apollo 将结果添加到数组的主要内容,如果未能解决你的问题,请参考以下文章

如何将 cookie 添加到 vue-apollo 请求中?

如何将 @vue/apollo-composable 添加到 Quasar 框架

vue-apollo 是不是可以从 Playground 返回不同的结果?

将对象数组添加到突变 react-graphql-apollo-mongoose 时,“无法读取未定义的属性 'get'”

创建突变后添加到 Apollo 客户端缓存中的数组

Vue Apollo:变量未添加到 graphql 查询,或者我在后端没有正确接受它们(Golang)