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

在Vue的<script setup>语法中如何展示Vue Apollo返回的数据

问题描述

参考Vue Apollo相关教程使用Fake API获取数据,但采用<script setup>语法时无法正确在页面展示返回数据,代码运行报错,寻求正确实现方式。

原Vue文件代码

<script setup>
    import { storeToRefs } from 'pinia';
    import { useAuthStore, useUsersStore } from '@/stores';

    import gql from 'graphql-tag'
    import { useQuery } from '@vue/apollo-composable'

    const authStore = useAuthStore();
    const { user: authUser } = storeToRefs(authStore);

    const usersStore = useUsersStore();
    const { users } = storeToRefs(usersStore);

    usersStore.getAll();

    apollo: gql`
        query Characters {
            characters {
            results {
                id
                name
                image
            }
        }
    }
    `
    const { result, loading, error } = useQuery(CHARACTERS_QUERY);
}
</script>
<template>
    <div>
        <h1>Hi {{authUser?.firstName}}!</h1>
        <div v-if="users.loading" class="spinner-border spinner-border-sm"></div>
        <div v-if="users.error" class="text-danger">Error loading users: {{users.error}}</div>
        <p v-if="error">Something went wrong...</p>
        <p v-if="loading">Loading...</p>
        <p v-else v-for="character in result.characters.results" :key="character.id">
            {{ character.name }}
        </p>
        <div></div>
    </div>
</template>

原main.js代码

import { createApp, provide, h } from 'vue';
import { createPinia } from 'pinia';

import App from './App.vue';
import { router } from './helpers';

// setup fake backend
import { fakeBackend } from './helpers';
fakeBackend();

import { ApolloClient, InMemoryCache } from '@apollo/client/core'
import { DefaultApolloClient } from '@vue/apollo-composable'
import { createApolloProvider } from '@vue/apollo-option'

const cache = new InMemoryCache()

const apolloClient = new ApolloClient({
  cache,
  uri: 'https://rickandmortyapi.com/graphql',
})

const apolloProvider = createApolloProvider({
  defaultClient: apolloClient,
})

const app = createApp({
  setup () {
    provide(DefaultApolloClient, apolloClient)
  },
  render: () => h(App),
})

app.use(apolloProvider)

app.use(createPinia());
app.use(router);

app.mount('#app');

问题分析与修正

你的代码存在3个关键错误,导致无法正常运行:

  • GraphQL查询定义错误:使用了选项式API的apollo:写法,且未定义后续引用的CHARACTERS_QUERY常量
  • 模板不安全访问:result初始值为null,直接访问result.characters.results会触发报错
  • 多余的Apollo配置:@vue/apollo-composable不需要createApolloProvider,两者共存会引发冲突

修正后的Vue文件代码

<script setup>
import { storeToRefs } from 'pinia';
import { useAuthStore, useUsersStore } from '@/stores';

import gql from 'graphql-tag'
import { useQuery } from '@vue/apollo-composable'

const authStore = useAuthStore();
const { user: authUser } = storeToRefs(authStore);

const usersStore = useUsersStore();
const { users } = storeToRefs(usersStore);

usersStore.getAll();

// 正确定义GraphQL查询常量
const CHARACTERS_QUERY = gql`
    query Characters {
        characters {
            results {
                id
                name
                image
            }
        }
    }
`;

// 调用useQuery获取响应式数据
const { result, loading, error } = useQuery(CHARACTERS_QUERY);
</script>
<template>
    <div>
        <h1>Hi {{ authUser?.firstName }}!</h1>
        <div v-if="users.loading" class="spinner-border spinner-border-sm"></div>
        <div v-if="users.error" class="text-danger">Error loading users: {{ users.error }}</div>
        
        <!-- 处理Apollo查询状态 -->
        <p v-if="error">Something went wrong...</p>
        <p v-if="loading">Loading...</p>
        <!-- 先判断result是否存在,避免初始null导致的报错 -->
        <template v-else-if="result">
            <p v-for="character in result.characters.results" :key="character.id">
                {{ character.name }}
            </p>
        </template>
    </div>
</template>

修正后的main.js代码

import { createApp, provide, h } from 'vue';
import { createPinia } from 'pinia';

import App from './App.vue';
import { router } from './helpers';

// setup fake backend
import { fakeBackend } from './helpers';
fakeBackend();

import { ApolloClient, InMemoryCache } from '@apollo/client/core'
import { DefaultApolloClient } from '@vue/apollo-composable'

const cache = new InMemoryCache()

const apolloClient = new ApolloClient({
  cache,
  uri: 'https://rickandmortyapi.com/graphql',
})

const app = createApp({
  setup () {
    provide(DefaultApolloClient, apolloClient)
  },
  render: () => h(App),
})

// 移除多余的apolloProvider配置
// app.use(apolloProvider)

app.use(createPinia());
app.use(router);

app.mount('#app');

核心说明

  1. 查询定义规范:在<script setup>中直接用变量存储GraphQL查询字符串,确保useQuery能正确引用
  2. 模板安全访问:通过v-else-if="result"判断数据是否加载完成,避免初始null值引发的属性读取错误
  3. Apollo配置精简:使用@vue/apollo-composable时,仅需在根组件setup中通过provide注入客户端即可,无需选项式API的createApolloProvider

内容的提问来源于stack exchange,提问作者Dev Related Cube

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 17:39:54