ApolloQuery
您可以使用 ApolloQuery
(或 apollo-query
)组件在您的模板中直接观看 Apollo 查询。阅读完本页后,请参阅 API 参考,了解所有可能的选项。
查询 gql 标签
这是使用 ApolloQuery
组件的推荐方法。它使用与其他示例中相同的语法,使用 gql
标签。
<template>
<ApolloQuery
:query="gql => gql`
query MyHelloQuery ($name: String!) {
hello (name: $name)
}
`"
:variables="{ name }"
>
<!-- TODO -->
</ApolloQuery>
</template>
我们将一个函数传递给 query
属性,该函数获取 gql
标签作为参数,因此我们可以直接编写 GraphQL 文档。
上面的示例还使用具有相同名称的属性将 variables
传递给查询。
在 ApolloQuery
的默认插槽中,您可以访问有关观看查询的各种插槽数据,例如 result
对象。
<template v-slot="{ result: { loading, error, data } }">
<!-- Loading -->
<div v-if="loading" class="loading apollo">Loading...</div>
<!-- Error -->
<div v-else-if="error" class="error apollo">An error occurred</div>
<!-- Result -->
<div v-else-if="data" class="result apollo">{{ data.hello }}</div>
<!-- No result -->
<div v-else class="no-result apollo">No result :(</div>
</template>
以下是完整的示例组件
<script>
export default {
data () {
return {
name: 'Anne'
}
}
}
</script>
<template>
<div>
<input v-model="name" placeholder="Enter your name">
<ApolloQuery
:query="gql => gql`
query MyHelloQuery ($name: String!) {
hello (name: $name)
}
`"
:variables="{ name }"
>
<template v-slot="{ result: { loading, error, data } }">
<!-- Loading -->
<div v-if="loading" class="loading apollo">Loading...</div>
<!-- Error -->
<div v-else-if="error" class="error apollo">An error occurred</div>
<!-- Result -->
<div v-else-if="data" class="result apollo">{{ data.hello }}</div>
<!-- No result -->
<div v-else class="no-result apollo">No result :(</div>
</template>
</ApolloQuery>
</div>
</template>
标签设置
如果您没有使用 vue-cli-plugin-apollo(v0.20.0+
),则需要配置 vue-loader 来转译字符串模板标签。vue-loader
在后台使用 Bublé 来转译组件模板中的代码。我们需要将 dangerousTaggedTemplateString
变换添加到 Bublé 以使 gql
工作。例如,使用 Vue CLI
// vue.config.js
module.exports = {
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap(options => {
options.transpileOptions = {
transforms: {
dangerousTaggedTemplateString: true,
},
}
return options
})
}
}
在原始 Webpack 配置中,它看起来像这样
module.exports = {
module: {
rules: [
{
test: /\.vue$/,
use: [
{
loader: 'vue-loader',
options: {
transpileOptions: {
transforms: {
dangerousTaggedTemplateString: true
}
}
}
}
]
},
/* Other rules ... */
]
}
}
使用 gql 文件的查询
使用该组件的另一种方法是创建单独的 .gql
文件。这些文件需要使用 graphql-tag 进行预处理。
<template>
<ApolloQuery
:query="require('../graphql/HelloWorld.gql')"
:variables="{ name }"
>
<template v-slot="{ result: { loading, error, data } }">
<!-- Loading -->
<div v-if="loading" class="loading apollo">Loading...</div>
<!-- Error -->
<div v-else-if="error" class="error apollo">An error occurred</div>
<!-- Result -->
<div v-else-if="data" class="result apollo">{{ data.hello }}</div>
<!-- No result -->
<div v-else class="no-result apollo">No result :(</div>
</template>
</ApolloQuery>
</template>
查询操作
您可以使用 query
插槽属性访问智能查询对象。以下是一个使用 fetchMore
对数据进行分页的示例组件
<template>
<ApolloQuery
:query="/* query */"
:variables="{
limit: $options.pageSize
}"
v-slot="{ result: { loading, error, data }, query }"
>
<!-- Display data here -->
<button v-if="hasMore" @click="loadMore(query)">Load more</button>
</ApolloQuery>
</template>
<script>
export default {
pageSize: 10,
data: {
return {
page: 1,
hasMore: true
}
},
methods: {
async loadMore (query) {
await query.fetchMore({
variables: {
offset: this.page++ * this.$options.pageSize
},
updateQuery: (prev, { fetchMoreResult }) => {
if (!fetchMoreResult || fetchMoreResult.product.length === 0) {
this.hasMore = false
return prev
}
return Object.assign({}, prev, {
product: [...prev.product, ...fetchMoreResult.product]
})
}
})
}
}
}
</script>
请参阅 API 参考,了解所有可能的智能查询方法。
使用片段
片段有助于在其他文档中共享 GraphQL 文档的部分,以一致地检索相同的数据,以及避免复制粘贴代码。
假设我们有这个 GetMessages
查询,它有一个 messages
字段,该字段是 Message
对象的数组
query GetMessages {
messages {
id
user {
id
name
}
text
created
}
}
我们希望将 messages
中 Message
类型的字段全部提取到一个片段中,以便我们可以在其他地方重用它。
首先,在组件中导入 gql
标签
import gql from 'graphql-tag'
然后,在组件定义中,声明一个新的 fragments
对象
export default {
fragments: {
/** TODO */
}
}
以下是应用于 Message
类型的 message
片段的样子
fragment message on Message {
id
user {
id
name
}
text
created
}
我们可以像对查询一样使用 gql
标签
export default {
fragments: {
message: gql`
fragment message on Message {
id
user {
id
name
}
text
created
}
`
}
}
在我们的组件中,我们现在可以使用 this.$options.fragments.message
访问片段。要在 GetMessages
查询中使用片段,我们需要使用 GraphQL ...
展开运算符,并将片段与查询一起放置
gql`
query GetMessages {
messages {
...message
}
}
${$options.fragments.message}
`
这将有效地生成以下 GraphQL 文档(您可以在 API 的 GraphQL playground 上尝试)
query GetMessages {
messages {
...message
}
}
fragment message on Message {
id
user {
id
name
}
text
created
}
这里发生了什么?GraphQL 会找到 ...
运算符,我们通常在查询中的 messages
字段中选择字段的位置。...
运算符后跟片段的名称 message
,然后查找整个 GraphQL 文档。在这里,我们已正确定义了片段,因此它就在查询下方。最后,GraphQL 会复制所有片段内容,并用它替换 ...message
。
最后,我们获得了最终的查询
query GetMessages {
messages {
id
user {
id
name
}
text
created
}
}
fragment message on Message {
id
user {
id
name
}
text
created
}
以下是完整的示例组件
<!-- MessageList.vue -->
<script>
import gql from 'graphql-tag'
export default {
fragments: {
message: gql`
fragment message on Message {
id
user {
id
name
}
text
created
}
`
}
}
</script>
<template>
<ApolloQuery
:query="gql => gql`
query GetMessages {
messages {
...message
}
}
${$options.fragments.message}
`"
>
<!-- Content... -->
</ApolloQuery>
</template>
重用片段
现在,我们可以在另一个组件中检索 message
片段
<!-- MessageForm.vue -->
<script>
import gql from 'graphql-tag'
import MessageList from './MessageList.vue'
export default {
methods: {
async sendMessage () {
await this.$apollo.mutate({
mutation: gql`
mutation SendMessage ($input: SendMessageInput!) {
addMessage (input: $input) {
newMessage {
...message
}
}
}
${MessageList.fragments.message}
`,
variables: {
/* variables here */
},
/* other options here */
})
}
}
}
</script>