我喜欢在特定的 pinia 商店中进行大量查询的想法,因为我可以在代码中的任何地方重用这些函数,但我正在努力实现它。我有以下pinia商店可以购买产品:
//using composition api in Pinia
import { ref } from 'vue';
import { defineStore } from 'pinia';
export const useProductStore = defineStore('product', () => {
const config = useRuntimeConfig();
const isLoading = ref(false);
const getProductData = async (id) => {
isLoading.value = true
try {
const query = gql`
query GetProductsById($id: ID!) {
product(id: $id) {
id
title
vendor
publishedAt
handle
variants(first: 100) {
nodes {
id
title
price {
amount
}
image {
url
altText
width
height
}
}
}
}
}
`
const variables = {
id: "gid://shopify/Product/" + id,
}
var results = await useAsyncQuery(query, variables);
isLoading.value = false
return results
} catch {
isLoading.value = false
return null
}
};
return {getProductData, isLoading};
});
然后在我的产品页面中,我尝试实现以下内容来显示结果:
<template>
<div class="bg-white">
{{ JSON.stringify(product.value) }}
</div>
</template>
<script setup>
import { ref } from 'vue'
import { storeToRefs } from 'pinia';
import { useProductStore } from '../stores/product-store';
import {useRoute } from 'vue-router'
const route = useRoute();
const productStore = useProductStore();
const { isLoading } = storeToRefs(productStore);
const product = computed(() => {
if (isLoading.value == true) {
return null;
} else {
return productStore.getProductData(route.query.id);
}
});
</script>
我这样做,并且 null 总是显示在屏幕上,但是我认为计算的属性将是反应性的,一旦异步函数完成,它应该显示我的数组的值。我确实尝试了 console.log(productStore.getProductData(route.query.id)) ,它将返回承诺并显示目标中的数据。我对 javascript 中的 async/await 也很不满意,所以我不确定这里出了什么问题。
有几个问题。
getProductData
不使用反应数据,.value
应在模板中省略,在计算结果中使用 Promise 之前需要对其进行解包。
产品数据应该是商店状态的一部分,不需要
isLoading
,因为null
意味着缺少数据:
const product = ref(null)
...
try {
product.value = await useAsyncQuery(...)
} catch {
product.value = null
}
return {product, getProductData}
getProductData
需要在组件中至少调用一次,无论是在 onMounted
中还是在与 Suspense
一起使用时在设置主体中调用。如果它需要对同一路线上的id
变化做出反应,应该有一个观察者:
watchEffect(() => {
productStore.getProductData(route.query.id);
});