在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');
核心说明
- 查询定义规范:在
<script setup>中直接用变量存储GraphQL查询字符串,确保useQuery能正确引用 - 模板安全访问:通过
v-else-if="result"判断数据是否加载完成,避免初始null值引发的属性读取错误 - Apollo配置精简:使用
@vue/apollo-composable时,仅需在根组件setup中通过provide注入客户端即可,无需选项式API的createApolloProvider
内容的提问来源于stack exchange,提问作者Dev Related Cube
相关产品推荐
相关产品推荐

