项目文件夹

文件
2026-07-13 21:36:20 +08:00

441 行
6.3 KiB
Markdown

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# GraphQL 变量模式
本参考文档涵盖在 GraphQL 操作中使用变量的模式。
## 目录
- [变量基础](#variable-basics)
- [变量类型](#variable-types)
- [默认值](#default-values)
- [复杂输入](#complex-inputs)
- [最佳实践](#best-practices)
## 变量基础
### 声明变量
变量在操作定义中声明:
```graphql
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}
```
### 使用变量
变量以 `$` 前缀引用:
```graphql
query GetUser($id: ID!) {
user(id: $id) {
# 此处使用 $id
id
name
}
}
```
### 传递变量
变量以独立的 JSON 对象形式传递:
```typescript
const { data } = await client.query({
query: GET_USER,
variables: {
id: "user_123",
},
});
```
### 多个变量
```graphql
query SearchPosts($query: String!, $status: PostStatus, $first: Int!, $after: String) {
searchPosts(query: $query, status: $status, first: $first, after: $after) {
edges {
node {
id
title
}
}
}
}
```
```json
{
"query": "graphql",
"status": "PUBLISHED",
"first": 10,
"after": "cursor_abc"
}
```
## 变量类型
### 标量类型
```graphql
query Example(
$id: ID!
$name: String!
$count: Int!
$price: Float!
$active: Boolean!
) {
# ...
}
```
### 自定义标量类型
```graphql
query Example(
$date: DateTime!
$email: Email!
$url: URL!
) {
# ...
}
```
### 枚举类型
```graphql
query GetPosts($status: PostStatus!) {
posts(status: $status) {
id
title
}
}
```
```json
{
"status": "PUBLISHED"
}
```
### 列表类型
```graphql
query GetUsers($ids: [ID!]!) {
users(ids: $ids) {
id
name
}
}
```
```json
{
"ids": ["user_1", "user_2", "user_3"]
}
```
### 输入对象类型
```graphql
mutation CreatePost($input: CreatePostInput!) {
createPost(input: $input) {
id
}
}
```
```json
{
"input": {
"title": "My Post",
"content": "Post content...",
"tags": ["graphql", "api"]
}
}
```
### 必需 vs 可选
```graphql
query Example(
$required: String! # 必须提供,不能为 null
$optional: String # 可以省略或为 null
$requiredList: [String!]! # 列表必填,元素必填
$optionalList: [String] # 列表可选,元素可选
) {
# ...
}
```
## 默认值
### 简单默认值
```graphql
query GetPosts($first: Int = 10, $status: PostStatus = PUBLISHED) {
posts(first: $first, status: $status) {
id
title
}
}
```
如果未提供,则使用默认值:
```json
{}
// 等效于:{ "first": 10, "status": "PUBLISHED" }
```
覆盖默认值:
```json
{
"first": 20
}
// 使用 first: 20,status: PUBLISHED(默认值)
```
### 可选变量的默认值
```graphql
# 变量为可选(无 !),但有默认值
query GetPosts($first: Int = 10) {
posts(first: $first) {
id
}
}
```
### 复杂类型的默认值
```graphql
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`
## 复杂输入
### 嵌套输入对象
```graphql
mutation CreateOrder($input: CreateOrderInput!) {
createOrder(input: $input) {
id
total
}
}
```
```json
{
"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"
}
}
}
```
### 输入对象列表
```graphql
mutation BulkCreateUsers($inputs: [CreateUserInput!]!) {
bulkCreateUsers(inputs: $inputs) {
id
email
}
}
```
```json
{
"inputs": [
{ "email": "user1@example.com", "name": "User 1" },
{ "email": "user2@example.com", "name": "User 2" },
{ "email": "user3@example.com", "name": "User 3" }
]
}
```
### 筛选输入
```graphql
query SearchProducts($filter: ProductFilter!) {
products(filter: $filter) {
id
name
price
}
}
```
```json
{
"filter": {
"category": "ELECTRONICS",
"priceRange": {
"min": 100,
"max": 500
},
"inStock": true,
"tags": ["featured", "sale"]
}
}
```
## 最佳实践
### 始终对动态值使用变量
```graphql
# 好:使用变量
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}
# 差:硬编码值
query GetUser {
user(id: "123") {
id
name
}
}
```
### 变量名与参数名保持一致
```graphql
# 好:关系清晰
query GetUser($userId: ID!) {
user(id: $userId) {
id
}
}
# 也不错:同名
query GetUser($id: ID!) {
user(id: $id) {
id
}
}
# 差:命名混乱
query GetUser($x: ID!) {
user(id: $x) {
id
}
}
```
### 使用描述性变量名
```graphql
# 好
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) {
# ...
}
```
### 对相关变量进行分组
```typescript
// 好:variables 对象反映输入结构
const variables = {
input: {
title: formData.title,
content: formData.content,
tags: formData.tags,
},
};
// 不够清晰:扁平变量
const variables = {
title: formData.title,
content: formData.content,
tags: formData.tags,
};
```
### 在客户端校验变量
```typescript
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 为变量提供类型
```typescript
// 从 schema 生成的类型
interface GetUserQueryVariables {
id: string;
}
// 配合 Apollo Client 使用
const { data } = useQuery<GetUserQuery, GetUserQueryVariables>(GET_USER, {
variables: { id: userId }, // 类型已检查
});
```