【发布时间】: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,而不是more。products.value.push(result.search.value.items)属于 watch 或 watchEffect ,需要检查它们是否可用于条件语句。const result = ... Object.assign(result ...- 这没有意义,useListProducts 已经返回了一个对象,分配给result并没有好处,这不会使它更具反应性。 -
感谢您的回复。我是 vue 新手,所以虽然我很欣赏你的帖子,但它对我一点帮助都没有:(