6.3 KiB
6.3 KiB
GraphQL 变量模式
本参考文档涵盖在 GraphQL 操作中使用变量的模式。
目录
变量基础
声明变量
变量在操作定义中声明:
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}
使用变量
变量以 $ 前缀引用:
query GetUser($id: ID!) {
user(id: $id) {
# 此处使用 $id
id
name
}
}
传递变量
变量以独立的 JSON 对象形式传递:
const { data } = await client.query({
query: GET_USER,
variables: {
id: "user_123",
},
});
多个变量
query SearchPosts($query: String!, $status: PostStatus, $first: Int!, $after: String) {
searchPosts(query: $query, status: $status, first: $first, after: $after) {
edges {
node {
id
title
}
}
}
}
{
"query": "graphql",
"status": "PUBLISHED",
"first": 10,
"after": "cursor_abc"
}
变量类型
标量类型
query Example(
$id: ID!
$name: String!
$count: Int!
$price: Float!
$active: Boolean!
) {
# ...
}
自定义标量类型
query Example(
$date: DateTime!
$email: Email!
$url: URL!
) {
# ...
}
枚举类型
query GetPosts($status: PostStatus!) {
posts(status: $status) {
id
title
}
}
{
"status": "PUBLISHED"
}
列表类型
query GetUsers($ids: [ID!]!) {
users(ids: $ids) {
id
name
}
}
{
"ids": ["user_1", "user_2", "user_3"]
}
输入对象类型
mutation CreatePost($input: CreatePostInput!) {
createPost(input: $input) {
id
}
}
{
"input": {
"title": "My Post",
"content": "Post content...",
"tags": ["graphql", "api"]
}
}
必需 vs 可选
query Example(
$required: String! # 必须提供,不能为 null
$optional: String # 可以省略或为 null
$requiredList: [String!]! # 列表必填,元素必填
$optionalList: [String] # 列表可选,元素可选
) {
# ...
}
默认值
简单默认值
query GetPosts($first: Int = 10, $status: PostStatus = PUBLISHED) {
posts(first: $first, status: $status) {
id
title
}
}
如果未提供,则使用默认值:
{}
// 等效于:{ "first": 10, "status": "PUBLISHED" }
覆盖默认值:
{
"first": 20
}
// 使用 first: 20,status: PUBLISHED(默认值)
可选变量的默认值
# 变量为可选(无 !),但有默认值
query GetPosts($first: Int = 10) {
posts(first: $first) {
id
}
}
复杂类型的默认值
query GetPosts($orderBy: PostOrderInput = { field: CREATED_AT, direction: DESC }) {
posts(orderBy: $orderBy) {
id
title
}
}
何时使用默认值
在以下场景使用默认值:
- 分页限制(
first: Int = 20) - 排序顺序(
direction: SortDirection = DESC) - 常见筛选值(
status: Status = ACTIVE) - 功能开关(
includeArchived: Boolean = false)
复杂输入
嵌套输入对象
mutation CreateOrder($input: CreateOrderInput!) {
createOrder(input: $input) {
id
total
}
}
{
"input": {
"customer": {
"email": "customer@example.com",
"name": "John Doe"
},
"items": [
{ "productId": "prod_1", "quantity": 2 },
{ "productId": "prod_2", "quantity": 1 }
],
"shippingAddress": {
"street": "123 Main St",
"city": "New York",
"state": "NY",
"zipCode": "10001",
"country": "US"
}
}
}
输入对象列表
mutation BulkCreateUsers($inputs: [CreateUserInput!]!) {
bulkCreateUsers(inputs: $inputs) {
id
email
}
}
{
"inputs": [
{ "email": "user1@example.com", "name": "User 1" },
{ "email": "user2@example.com", "name": "User 2" },
{ "email": "user3@example.com", "name": "User 3" }
]
}
筛选输入
query SearchProducts($filter: ProductFilter!) {
products(filter: $filter) {
id
name
price
}
}
{
"filter": {
"category": "ELECTRONICS",
"priceRange": {
"min": 100,
"max": 500
},
"inStock": true,
"tags": ["featured", "sale"]
}
}
最佳实践
始终对动态值使用变量
# 好:使用变量
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}
# 差:硬编码值
query GetUser {
user(id: "123") {
id
name
}
}
变量名与参数名保持一致
# 好:关系清晰
query GetUser($userId: ID!) {
user(id: $userId) {
id
}
}
# 也不错:同名
query GetUser($id: ID!) {
user(id: $id) {
id
}
}
# 差:命名混乱
query GetUser($x: ID!) {
user(id: $x) {
id
}
}
使用描述性变量名
# 好
query SearchPosts(
$searchQuery: String!
$authorId: ID
$publishedAfter: DateTime
$maxResults: Int = 20
) {
searchPosts(
query: $searchQuery
author: $authorId
after: $publishedAfter
first: $maxResults
) {
# ...
}
}
# 差
query SearchPosts($q: String!, $a: ID, $d: DateTime, $n: Int) {
# ...
}
对相关变量进行分组
// 好:variables 对象反映输入结构
const variables = {
input: {
title: formData.title,
content: formData.content,
tags: formData.tags,
},
};
// 不够清晰:扁平变量
const variables = {
title: formData.title,
content: formData.content,
tags: formData.tags,
};
在客户端校验变量
function createPost(input: CreatePostInput) {
// 发送前校验
if (!input.title?.trim()) {
throw new Error("Title is required");
}
if (input.title.length > 200) {
throw new Error("Title too long");
}
return client.mutate({
mutation: CREATE_POST,
variables: { input },
});
}
使用 TypeScript 为变量提供类型
// 从 schema 生成的类型
interface GetUserQueryVariables {
id: string;
}
// 配合 Apollo Client 使用
const { data } = useQuery<GetUserQuery, GetUserQueryVariables>(GET_USER, {
variables: { id: userId }, // 类型已检查
});