使用 GraphQL 查询和变更数据
约 655 字大约 2 分钟
GraphQLQueryMutation
2026-04-08
本文介绍 GraphQL 客户端侧的查询语法:如何写 Query、Mutation、Subscription,以及常用的进阶特性。
1. 基础查询(Query)
假设服务端 Schema 中有:
type Query {
user(id: ID!): User
users: [User!]!
}最简单的查询语句:
{
user(id: "1") {
id
name
email
}
}返回:
{
"data": {
"user": {
"id": "1",
"name": "ZhenYu",
"email": "zhenyu@example.com"
}
}
}客户端只取了三个字段,其他字段(即使 Schema 中存在)不会被返回。
2. 命名查询与变量
生产代码中应使用具名查询并传递变量,而非字符串拼接:
query GetUser($id: ID!) {
user(id: $id) {
id
name
posts {
title
}
}
}变量:
{ "id": "1" }好处:可被服务端缓存、安全防注入、便于调试。
3. 别名(Alias)与多查询
一次请求多个同名字段时使用别名:
query {
me: user(id: "1") {
name
}
friend: user(id: "2") {
name
}
}4. 片段(Fragment)
复用字段选择集:
fragment UserInfo on User {
id
name
email
}
query {
me: user(id: "1") {
...UserInfo
}
friend: user(id: "2") {
...UserInfo
}
}5. 指令(Directive)
内置指令:
@include(if: Boolean):条件包含字段@skip(if: Boolean):条件跳过字段
query GetUser($id: ID!, $withPosts: Boolean!) {
user(id: $id) {
name
posts @include(if: $withPosts) {
title
}
}
}6. 变更(Mutation)
写操作使用 mutation 关键字,语法与 Query 一致,但语义上会修改数据,多个字段会按顺序串行执行:
mutation CreatePost($input: CreatePostInput!) {
createPost(input: $input) {
id
title
createdAt
author {
name
}
}
}变量:
{
"input": {
"title": "Hello GraphQL",
"content": "..."
}
}Mutation 的返回值通常包含新创建/更新后的完整对象,便于客户端立即更新本地缓存。
7. 订阅(Subscription)
基于 WebSocket 推送实时数据:
subscription OnPostCreated {
postCreated {
id
title
author {
name
}
}
}客户端接入需使用支持 subscriptions-transport-ws 或 graphql-ws 协议的客户端,如 Apollo Client 的 GraphQLWsLink。
8. 接口与联合类型的查询
当字段类型是 Interface 或 Union 时,需要使用内联片段指定具体类型:
query Search($keyword: String!) {
search(keyword: $keyword) {
__typename
... on User {
name
}
... on Post {
title
}
}
}__typename 是每个对象都自带的元字段,用于运行时辨别类型。
9. 错误处理
GraphQL 响应包含 data 和 errors 两个顶层字段。即便部分字段解析失败,其余字段仍可能返回:
{
"data": { "user": { "name": "ZhenYu", "posts": null } },
"errors": [
{
"message": "Failed to load posts",
"path": ["user", "posts"],
"extensions": { "code": "INTERNAL_ERROR" }
}
]
}客户端应同时处理两者,而非只看 HTTP 状态码(GraphQL 一般永远返回 200)。
10. 使用 graphql-request 发起请求
最轻量的客户端之一:
import { GraphQLClient, gql } from 'graphql-request'
const client = new GraphQLClient('/graphql', {
headers: { Authorization: `Bearer ${token}` },
})
const query = gql`
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}
`
const data = await client.request(query, { id: '1' })