概述
在上节课中,我们学习了如何使用接口来定义在不同类型中共享的常见属性。我们还学习了如何为那些常见属性编写查询。
但当我们尝试为其它字段对特定实现类型是唯一的时会发生什么?例如,在 Airlock 中,Review.author
字段返回一个实现User
接口的对象,该对象可以是Host
或Guest
。房东和客人有一些字段他们不会相互共享,例如Host.listings
或Guest.funds
。
我们知道返回接口的字段可以返回任何实现该接口的对象类型。那么我们如何知道返回对象上将有哪些其它字段?
要回答这个问题,我们需要另一个GraphQL工具:查询片段。
在本课中,我们将
- 了解内联和命名片段。
- 了解如何 查询 接口以及实现对象类型,使用内联和命名 片段。
查询接口的共享字段
我们可以查询 字段该字段以与查询其他类型和字段相同的方式返回一个接口。
我们以 query
关键字开头,后跟 查询 的名称,之后是大括号。在大括号内,我们可以查询接口中概述的 字段。
我们来看 Airlock 中的示例 查询。此 查询 使用 me
操作,该操作返回已登录的 User
。我们还要求提供 name
和 profilePicture
字段,它们是 Airlock 用户个人资料页面中显示的详细信息。
query GetMyProfile {me {nameprofilePicture}}
用户个人资料页面还显示其他信息,具体取决于您是房东还是客人。对于房东,我们要显示他们的个人资料描述。对于房客,我们要显示他们钱包中的当前资金数额。
我们无法立即将这些字段添加到我们的查询中,因为这些字段属于它们特定的Host
或Guest
类型,并且me
字段返回User
接口。如果我们尝试将funds
字段添加到我们现有的查询中,我们将得到一个错误,因为User
接口没有funds
字段。
要查询附加的角色特定字段,我们需要使用片段。
GraphQL 片段
一个GraphQL 片段是从对象类型中提取的字段的子集,你可以重复使用它们并在多个GraphQL 操作之间共享这些字段。
命名片段
要定义 片段,我们从 fragment
关键字开始,然后是 片段 的名称(说明其用途)。然后,我们添加关键字 on
,后面是 片段 的关联类型。在大括号内,我们列出该关联类型对应的 字段。
fragment HostProfileFields on Host {profileDescription}fragment GuestProfileFields on Guest {funds}
要在我们的原始 查询 中使用这些 片段,我们将它们包括在我们的 字段 选择集 中。我们通过将片段名称前置三个句点(...
)来执行此操作,类似于 JavaScript 的扩展语法。
query GetMyProfile {me {nameprofilePicture...HostProfileFields...GuestProfileFields}}fragment HostProfileFields on Host {profileDescription}fragment GuestProfileFields on Guest {funds}
注意:您可以在下一部分中的 GraphOS Studio 沙盒中测试此 查询。
这些 片段 是 已命名片段,它们用于在不同的查询之间重用是很方便的。
内联片段
我们还可以用内嵌片段得到类似的内嵌片段。为此,我们将我们查询中的已命名片段替换为片段本身的内容,保留我们的三个时期 (...
),然后指定类型名称 (on Host
或on Guest
)。当我们不必在操作之间重用片段时,这会很方便。
通过内嵌片段,查询看起来像这样:
query GetMyProfile {me {nameprofilePicture... on Host {profileDescription}... on Guest {funds}}}
现在,如果登录用户是房东,我们获取其profileDescription
,如果登录用户是客人,我们获取其funds
。(并且在所有情况下,我们获取用户的name
和profilePicture
。)
测试查询
要查看这些片段起作用,让我们使用 Airlock 测试一些查询GraphQL 服务器。
让我们来构建查询以便使用__typename
和内嵌片段获取个人详细信息。
query GetMyProfile {me {__typenamenameprofilePicture... on Host {profileDescription}... on Guest {funds}}}
现在,让我们测试一下我们的 查询!
打开一个新的浏览器窗口,转到https://127.0.0.1:4000,然后单击按钮在GraphOS Studio沙盒中查询您的服务器。
由于 Airlock 需要认证,我们需要在 Headers 选项卡中添加一个
Authorization
标头。将标头值设置为Bearer user-1
(适用于主机)或Bearer user-2
(适用于访客)。将以上查询复制到 Explorer 中并运行。
响应应类似于以下内容之一
我们还可以尝试使用命名的碎片(如下所示)执行相似查询。我们将获取与内联碎片查询相同的数据!
query GetMyProfile {me {__typenamenameprofilePicture...HostProfileFields...GuestProfileFields}}fragment HostProfileFields on Host {profileDescription}fragment GuestProfileFields on Guest {funds}
在 Airlock 代码库中查看
整个查询在 Airlock 客户端代码中使用了多个碎片。查看以下示例:
- 在
client/src/utils.js
中定义的LISTING_FRAGMENT
- 在
Host
和Guest
上对GET_USER
查询中的内联碎片(在client/src/utils.js
中定义) - 对
Host
在UPDATE_PROFILE
变异中的内联碎片(在client/src/pages/profile.js
中定义)
实践
使用以下架构完成接下来的两个代码挑战
type Query {availableBooks: [Book]borrowedBooks(userId: ID!): [Book]}interface Book {isbn: ID!title: String!genre: String!}type PictureBook implements Book {isbn: ID!title: String!genre: String!numberOfPictures: IntisInColor: Boolean}type YoungAdultNovel implements Book {isbn: ID!title: String!genre: String!wordCount: IntnumberOfChapters: Int}
通过声明两个已命名碎片来完成以下查询。一个名为 PictureBookFields
位于 PictureBook
类型上,用于检索 numberOfPictures
和 isInColor
的字段。另一个名为 YANovelFields
位于 YoungAdultNovel
类型上,用于检索 wordCount
和 numberOfChapters
的字段。在 GetAvailableBooks
查询中使用这些已命名的碎片。
修改以下查询以使用内联碎片。
要点
- 片段是一个子集,通常用于多个查询和突变。
- 要查询接口及其实现类型,我们需要使用命名或内联片段。
- 命名片段可以独立存在,非常适合在多个查询中重复使用。
- 内联片段可以在查询中轻松编写和读取。
结论
干得好,您已了解了四个新的GraphQL概念,您可以在设计自己的架构时使用它们!
如果您有兴趣更深入地了解本侧任务中涵盖的主题,请查看以下附加资源列表。
至于下一步,您可以查看身份验证和授权侧任务,或深入了解Voyage 系列以了解如何使用Apollo Federation模块化您的图。
附加资源
- Apollo 文档:GraphQL 架构基础:有关枚举和输入类型的更多信息
- Apollo 文档:联合和接口
- Apollo 文档:片段
- GraphQL 文档:架构和类型:有关枚举、输入类型和接口的更多信息
- GraphQL 文档:查询和突变有关片段的更多信息