片段
的GraphQL 规范定义了两种类型的 片段:
命名和内联 片段 都可以用作 类型条件,这允许您访问 聚合类型 的 字段。
阅读关于 类型条件 的指南以了解更多信息。
命名的片段
命名的 片段 定义在 .graphql
文件,就像一个操作定义。一个命名的碎片始终有一个名称和一个“父类型”,即它可以应用到的模式中的类型。此碎片可以包含在操作定义的选择集中。
Apollo iOS为命名的碎片生成单独的结果类型,这意味着它们是一种保持UI组件或工具函数独立于特定查询的极佳方式。
fragment HeroDetails on Character {nameappearsIn}
query HeroAndFriends {hero {name...HeroDetailsfriends {...HeroDetails}}}
Apollo iOS为HeroDetails
碎片生成一个类型安全的模型,看起来像这样(省略详情以关注类结构):
struct HeroDetails: MySchema.SelectionSet, Fragment {let name: Stringlet appearsIn: [Episode]}
为HeroAndFriendsQuery
生成的结果数据模型将包括HeroDetails
碎片的字段,并且能够转换为HeroDetails
模型的格式。
class HeroAndFriendsQuery: GraphQLQuery {struct Data: SelectionSet {let hero: Herostruct Hero: SelectionSet {let name: Stringlet friends: [Friend]let appearsIn: [Episode]// Fragment Conversion Declarationvar fragments: Fragmentsstruct Fragments {var heroDetails: HeroDetails { ... }}struct Friend: SelectionSet {let name: Stringlet appearsIn: [Episode]// Fragment Conversion Declarationvar fragments: Fragmentsstruct Fragments {var heroDetails: HeroDetails { ... }}}}}}
碎片转换
一个定义中包含碎片的结果模型将包含一个Fragments
结构体以支持碎片的转换。
以上Hero
和Friend
模型均包含Fragments
结构体,并且可以被转换为HeroDetails
碎片
let hero: HeroDetails = data.hero.fragments.heroDetailslet friends: [HeroDetails] = data.hero.friends.map { $0.fragments.heroDetails }
碎片重用
碎片转换允许您在不同操作或同一操作内的多个对象间重用碎片作为通用模型。
一种常见的模式是为子视图定义碎片,并在父级定义的查询中包含这个碎片。这样,子视图可以轻松重用,并且只依赖于它所需的特定数据。
上面的HeroDetails
碎片被用于Hero
和Friend
模型,但可以通过显示一个包含HeroDetails
碎片模型的视图列表来在你的应用程序中显示英雄与其朋友。
struct HeroDetailsListView: View {let data: HeroAndFriendsQuery.Datavar body: some View {VStack {HeroDetailsView(hero: data.hero.fragments.heroDetails)for friend in data.hero.friends {HeroDetailsView(hero: friend.fragments.heroDetails)}}}}struct HeroDetailsView: View {let hero: HeroDetailsvar body: some View {HStack {Text(hero.name)Text(hero.appearsIn.description)}}}
您可以向HeroDetails
碎片添加更多数据,并在HeroDetailsView
中显示这些数据,而不会对父视图造成任何影响。此外,HeroDetailsView
可用于包含HeroDetails
碎片的任何其他GraphQL操作
内联碎片
内联碎片是一个没有名称的碎片。它在另一个定义中“内联”声明,无法重用。内联碎片可以包含在操作定义、命名碎片定义中,或嵌套在另一个内联碎片内。它们通常用于使用类型条件或@skip
/@include
指令有条件地包含字段
Apollo iOS不会为内联碎片生成单个模型,而是影响包含它们的操作或碎片的生成模型。
您可以使用内联碎片和类型条件来查询类型特定的字段:
query HeroAndFriends($episode: Episode) {hero(episode: $episode) {name... on Droid {primaryFunction}}}
内联碎片与类型条件的结果将通过特别生成的as<Type>
属性提供:
let name: String = data.hero.namelet primaryFunction: String = data.hero.asDroid?.primaryFunction
有关如何使用内联碎片作为类型条件的更多信息,请参阅类型条件文档。