You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js结合Pinia异步处理GraphQL数据时的过滤报错问题

解决Pinia中useQuery数据未就绪导致的报错问题

核心问题分析

你把useQuery直接放在Pinia选项式的state里,这不符合Vue Apollo的使用规范——useQuery是组合式API钩子,必须在组件或store的setup函数中调用。同时,filterItems getter在数据未加载时直接访问state.resultItems.result.items,会因result未就绪抛出错误。

解决方案步骤

1. 重构Pinia Store为Setup语法

将选项式store改为setup形式,正确管理Apollo查询状态:

import { defineStore, ref, computed } from "pinia"
import { useQuery } from '@vue/apollo-composable'
import { ITEMS_QUERY, SKU_QUERY} from '@/graphql/queries'

export const useHomePage = defineStore('homeStore', () => {
  // 初始化商品列表查询
  const { result: itemsResult, loading: itemsLoading } = useQuery(ITEMS_QUERY, { itemBrand: "Estera" })
  // 初始化SKU查询,复用refetch避免重复创建实例
  const { result: skuResult, refetch: refetchSku } = useQuery(SKU_QUERY, { itemName: '' })

  // 定义响应式状态
  const nameItem = ref('')
  const activeSurface = ref('')
  const activeColor = ref('')
  const imageItem = ref('')
  const imagesItem = ref('')
  const windowsSillLength = ref(100)
  const mainColl = ref(1)

  // 处理去重后的颜色列表,添加空值安全判断
  const filterItems = computed(() => {
    // 数据未就绪时返回空数组
    if (!itemsResult.value?.items) return []
    return [...new Map(itemsResult.value.items.map(item => [item.colorName, item])).values()]
  })

  // 获取第一个商品名称,加入空值校验
  function getNameItem() {
    if (!nameItem.value && filterItems.value.length > 0) {
      nameItem.value = filterItems.value[0].title
    }
    return nameItem.value
  }

  // 重新获取SKU数据,使用refetch更新查询
  async function getSku(nameItemVal, surface, color, imageItemVal, imagesItemVal) {
    await refetchSku({ itemName: nameItemVal })
    activeSurface.value = surface
    nameItem.value = nameItemVal
    activeColor.value = color
    imageItem.value = imageItemVal
    imagesItem.value = imagesItemVal
    windowsSillLength.value = 100
    mainColl.value = 1
  }

  return {
    // 查询状态
    itemsLoading,
    // 响应式变量
    nameItem, activeSurface, activeColor, imageItem, imagesItem,
    // 计算属性与方法
    filterItems, getNameItem, getSku
  }
})

2. 组件中添加加载状态处理

在模板中判断数据是否加载完成,避免渲染未就绪内容:

<template>
  <!-- 加载状态提示 -->
  <div v-if="HomePage.itemsLoading" class="loading">加载中...</div>

  <!-- 数据就绪后渲染内容 -->
  <div v-else>
    <div class="text-3xl leading-[44px] text-left">{{ HomePage.getNameItem() }}</div>

    <div class="inputs_block">
      <div class="name_color mb-4">
        <span class="name text-base leading-6 text-black">Цвет:</span>
        <span class="value text-sm leading-18px text-[#707070] ml-[5px]">{{ HomePage.activeColor }}</span>
      </div>

      <div class="flex gap-x-0.5 flex-wrap ml-[-5px]">
        <span
          v-for="color in filterItems"
          :key="color.colorName" <!-- 用唯一值做key,避免索引问题 -->
          :class="HomePage.activeColor === color.colorName ? 'border-[#CAA381]' : 'border-white'"
          @click="HomePage.getSku(color.title, color.surfaceName, color.colorName, color.image, color.morePhoto)"
          class="group w-[52px] h-[52px] relative flex justify-center items-center -mt-2 mb-2.5 rounded-[7px] border-2 border-solid hover:cursor-pointer hover:border-[#CAA381]"
        >
          <img class="rounded w-[42px] h-[42px]" :src="color.colorUrl" alt="">
          <p class="group-hover:block bg-[#F5F3F1] hidden absolute text-xs leading-[14px] text-center text-black bottom-[-30px] w-[max-content] z-[1] px-[3px] py-[5px] rounded-lg">{{ color.colorName }}</p>
        </span>
      </div>
    </div>
  </div>
</template>

<script setup>
import { storeToRefs } from "pinia"
import { useHomePage } from '@/stores/HomePageStore'
const HomePage = useHomePage()
const { filterItems } = storeToRefs(HomePage)
</script>

关键改进点

  • 规范useQuery使用:在Pinia的setup函数中调用useQuery,直接获取响应式的result、loading状态,而非将查询对象存入state。
  • 空值安全校验:在filterItems中用可选链itemsResult.value?.items判断数据是否就绪,未就绪时返回空数组避免报错。
  • 优化SKU查询逻辑:使用refetch方法更新查询,避免重复创建useQuery实例,保持状态一致性。
  • 加载状态管理:通过itemsLoading控制渲染流程,用户不会看到未就绪的错误内容。
  • v-for key优化:用唯一的colorName作为循环key,提升渲染性能与正确性。

内容的提问来源于stack exchange,提问作者Kyrylo Brodnikov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 04:43:28