GraphQL 代码生成
这是一个关于将 GraphQL 代码生成为 Dart/Flutter 的有见地的工具。
它将允许您用最少的配置生成 Dart 序列化器和客户端助手。
该框架不对您的片段或查询的结构做出任何假设,
对于每个 operation.graphql,框架将生成一个 operation.graphq.dart 文件
其中包含 Dart 类。
有关该工具和动机的更多信息,请参阅 GraphQL 代码生成深入分析
以及如何使用该工具构建您的 Flutter 应用,请参阅 构建您的 Flutter GraphQL 应用。
构建器依赖于 json_serializable 来生成实际的序列化器,
因此,除了上面提到的两个文件之外,它还将生成一个 operation.graphql.g.dart
文件。
该框架不会为您获取您的 schema,因此在运行此命令之前,您需要
将您的 schema 添加到您的项目中。
安装
将 graphql_codegen: <current_version> 添加到您的 dev_dependencies。
该项目依赖于 json_serializable,因此请在此处了解如何设置 此处。
它也是一个构建器,因此您需要设置 build_runner。在此处了解更多 此处。
基本用法
要从 GraphQL schema 生成 Dart 类,首先需要创建一个 schema.graphql 文件和 GraphQL 文档文件。
例如
给定 schema
# schema.graphql
type Query {
fetch_person(id: ID!): Person
}
type Person {
full_name: String!
nickname: String
website: URL
date_of_birth: ISODateTime
parents: [Person!]
siblings: [Person!]
children: [Person!]
}
scalar ISODateTime
scalar URL
和一个查询
# person.graphql
query FetchPerson($id: ID!) {
fetch_person(id: $id) {
name: full_name
}
}
然后您可以使用以下命令生成 Dart 类
$ dart run build_runner build
之后,您可以使用以下方法解析结果
// person.dart
import 'person.graphql.dart';
main () {
final data = fetchDataFromSomewhereMaybeOuterSpace();
final parsedData = QueryFetchPerson.fromJson(data);
final name = parsedData.fetchPerson?.name;
print(name);
}
使用片段
片段是重用应用中查询的绝佳工具。它们用于创建“接口”
这使得您可以轻松地在应用中解析数据。给定上面的 schema 和查询
# parents_and_children.graphql
fragment PersonSummary on Person {
full_name
}
query FetchParentsAndChildren {
fetch_person(id: "1") {
parents {
...PersonSummary
nickname
}
children {
...PersonSummary
}
}
}
这将允许您执行以下操作
// parents_and_children.dart
import 'parents_and_children.graphql.dart';
printPerson(FragmentPersonSummary person) {
print(person.fullName);
}
main () {
final data = fetchDataFromTheVoid();
final parsedData = QueryFetchParentsAndChildren.fromJson(data);
for (final parent in parsedData?.fetchPerson.parents ?? []) {
printPerson(parent);
print(parent.dob);
}
for (final child in parsedData?.fetchPerson.children ?? []) {
printPerson(child);
}
}
FragmentPersonSummary 是一个抽象类,其形状为
...
abstract class FragmentPersonSummary {
String get fullName;
}
...
并将在生成的 .graphql.dart 文件中可用,用于包含片段的 .graphql 文件
包含片段。
自定义标量
开箱即用,标准片段都受支持并映射到相关的 Dart 类型。您可以添加
新映射用于自定义标量或覆盖现有配置。
在上面的 schema 中,您可以看到我们定义了 ISODateTime 标量。在此示例中,它包含
一个带有 iso 格式日期时间字符串的字符串。我们希望通过以下方式将其映射到 Dart 的 DateTime 类型
将以下配置添加到 build.yaml 文件中
# build.yaml
targets:
$default:
builders:
graphql_codegen:
options:
scalars:
ISODateTime:
type: DateTime
JSON:
type: Map<String, dynamic>
由于 json_serializable 支持从字符串解析 DateTime,因此这就是我们所需要做的。
假设我们想使用自定义日期时间类(例如 CustomDateTime),我们可以添加
# build.yaml
targets:
$default:
builders:
graphql_codegen:
options:
scalars:
ISODateTime:
type: CustomDateTime
fromJsonFunctionName: customDateTimeFromJson
toJsonFunctionName: customDateTimeToJson
import: package:my_app/scalar.dart
并创建一个 scalar.dart 文件,其中包含您的转换器函数和类。
// custom_date_time.dart
class CustomDateTime {
final String datetime;
CustomDateTime(this.datetime);
}
and
// scalar.dart
export 'custom_date_time.dart' show {CustomDateTime};
CustomDateTime customDateTimeFromJson(dynamic data) => CustomDateTime(data as String);
dynamic customDateTimeToJson(CustomDateTime time) => time.datetime;
现在所有使用 ISODateTime 的字段都将是 CustomDateTime 实例。
客户端
解析数据很好,但实际上并不十分实用。因此,我们可以生成
客户端来调用您的 API。
可以在 build.yaml 文件中使用以下配置启用客户端
# build.yaml
targets:
$default:
builders:
graphql_codegen:
options:
clients:
- graphql
- graphql_flutter
目前,我们支持两个客户端
客户端 graphql
在设置好 graphql 客户端后(请参阅 pub.dev/packages/graphql),您可以使用
GraphQL 代码生成来生成客户端上的新查询或变异。
使用上面的查询
# person.graphql
query FetchPerson($id: ID!) {
fetch_person(id: $id) {
name: full_name
}
}
我们现在可以访问客户端
import 'person.graphql.dart';
main () async {
final client = GraphQLClient();
final result = await client.queryFetchPerson(
GQLOptionsQueryFetchPerson(
variables: VariablesQueryFetchPerson(
id: "1",
),
),
);
final parsedData = result.parsedBodyQueryFetchPerson;
print(parsedData?.fetchPerson?.name);
}
客户端 graphql_flutter
在设置好 graphql_flutter 客户端后(请参阅 pub.dev/packages/graphql_flutter),
您可以使用 GraphQL 代码生成来生成新的 Query 或 Mutation 小部件。
使用上面的查询
# person.graphql
query FetchPerson($id: ID!) {
fetch_person(id: $id) {
name: full_name
}
}
我们可以使用小部件进行查询
import 'person.graphql.dart';
import 'package:flutter/widgets.dart';
class PersonWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GQLFQueryFetchPerson(
options: GQLOptionsQueryFetchPerson(
variables: VariablesQueryFetchPerson(
id: 'id',
),
),
builder: (result, {fetchMore, refetch}) {
return Text(
result.parsedDataQueryFetchPerson?.fetchPerson?.name ?? '...loading'
);
}
);
}
}