GraphQL之根底篇 - 查问和变更
字段(Fields)
GraphQL申请对象上的特定字段,例:
// 申请{ hero { name friends { name } }}// 响应{ "data": { "hero": { "name": "R2-D2", "friends": [ { "name": "Luke Skywalker" }, { "name": "Han Solo" } ] } }}
咱们能够发现,查问和后果领有一样的构造和字段。这是 GraphQL 最重要的个性,因为这样一来,你就总是能失去你想要的数据,而服务器也精确地晓得客户端申请的字段。
参数(Arguments)
申请传参是必要的,也能够让查问变得更加灵便和不便,当然GraphQL也能够做到。
// 申请{ human(id: "1000") { name height }}// 响应{ "data": { "human": { "name": "Luke Skywalker", "height": 1.72 } }}
别名(Aliases)
当须要重命名返回的字段名时,别名就有能够起到作用,如下例能够将hero替换为empireHero和jediHero。
// 申请{ empireHero: hero(episode: EMPIRE) { name } jediHero: hero(episode: JEDI) { name }}// 响应{ "data": { "empireHero": { "name": "Luke Skywalker" }, "jediHero": { "name": "R2-D2" } }}
片段(Fragments)
当咱们的申请中有有反复字段须要展现时,别离列出可能会显得比拟臃肿,这就是为何 GraphQL 蕴含了称作片段的可复用单元,上面例子展现了如何应用片段解决上述场景:
// 申请{ leftComparison: hero(episode: EMPIRE) { ...comparisonFields } rightComparison: hero(episode: JEDI) { ...comparisonFields }}fragment comparisonFields on Character { name appearsIn friends { name }}// 响应{ "data": { "leftComparison": { "name": "Luke Skywalker", "appearsIn": [ "NEWHOPE", "EMPIRE", "JEDI" ], "friends": [ { "name": "Han Solo" } ] }, "rightComparison": { "name": "R2-D2", "appearsIn": [ "NEWHOPE", "EMPIRE", "JEDI" ], "friends": [ { "name": "Leia Organa" } ] } }}
有了片段,能够大大简化咱们的代码。片段的概念常常用于将简单的利用数据需要宰割成小块,特地是你要将大量不同片段的 UI 组件组合成一个初始数据获取的时候。
操作名称(Operation name)
这之前,咱们都应用了简写句法,省略了 query 关键字和查问名称,然而生产中应用操作类型和操作名称能够使咱们代码缩小歧义。
上面的示例蕴含了作为操作类型的关键字 query 以及操作名称 HeroNameAndFriends:
// 申请query HeroNameAndFriends { hero { name friends { name } }}// 响应{ "data": { "hero": { "name": "R2-D2", "friends": [ { "name": "Luke Skywalker" }, { "name": "Leia Organa" } ] } }}
操作类型能够是 query、mutation 或 subscription,形容你打算做什么类型的操作。操作类型是必须的,除非你应用查问简写语法,在这种状况下,你无奈为操作提供名称或变量定义。
操作名称是你的操作的有意义和明确的名称。
变量(Variables)
目前为止,咱们将参数写在了查问字符串内。然而在很多利用中,字段的参数可能是动静的,如下例,可使咱们的申请更加灵便。
// 定义变量{ "episode": "JEDI"}// 申请query HeroNameAndFriends($episode: Episode) { hero(episode: $episode) { name friends { name } }}
变量定义(Variable definitions)
变量定义看上去像是上述查问中的 ($episode: Episode)。其工作形式跟类型语言中函数的参数定义一样。它以列出所有变量,变量前缀必须为 $,后跟其类型,本例中为 Episode。
变量定义能够是可选的或者必要的。上例中,Episode 后并没有 !,因而其是可选的。然而如果你传递变量的字段要求非空参数,那变量肯定是必要的。
默认变量(Default variables)
能够通过在查问中的类型定义前面附带默认值的形式,将默认值赋给变量。
query HeroNameAndFriends($episode: Episode = "JEDI") { hero(episode: $episode) { name friends { name } }}
指令(Directives)
咱们可能须要应用变量动静地扭转咱们查问的构造,如下例:
// 定义变量{ "episode": "JEDI", "withFriends": false}// 申请query Hero($episode: Episode, $withFriends: Boolean!) { hero(episode: $episode) { name friends @include(if: $withFriends) { name } }}// 响应{ "data": { "hero": { "name": "R2-D2" } }}
咱们用了 GraphQL 中一种称作指令的新个性。一个指令能够附着在字段或者片段蕴含的字段上。
GraphQL 的外围标准蕴含两个指令:
- @include(if: Boolean) 仅在参数为 true 时,蕴含此字段。
- @skip(if: Boolean) 如果参数为 true,跳过此字段。
变更(Mutations)
GraphQL 建了一个约定来标准任何写入的操作,都应该显式通过变更(mutation)来发送。
// 定义变量{ "ep": "JEDI", "review": { "stars": 5, "commentary": "This is a great movie!" }}// 变更申请mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) { createReview(episode: $ep, review: $review) { stars commentary }}// 响应{ "data": { "createReview": { "stars": 5, "commentary": "This is a great movie!" } }}
一个变更也能蕴含多个字段,一如查问。查问和变更之间名称之外的一个重要区别是:
查问字段时,是并行执行,而变更字段时,是线性执行,一个接着一个。
这意味着如果咱们一个申请中发送了两个 incrementCredits 变更,第一个保障在第二个之前执行,以确保咱们不会呈现竞态。
内联片段(Inline Fragments)
如果你查问的字段返回的是接口或者联结类型,那么你可能须要应用内联片段来取出上层具体类型的数据:
// 定义变量{ "ep": "JEDI"}// 申请query HeroForEpisode($ep: Episode!) { hero(episode: $ep) { name ... on Droid { primaryFunction } ... on Human { height } }}// 响应{ "data": { "hero": { "name": "R2-D2", "primaryFunction": "Astromech" } }}
这个查问中,hero 字段返回 Character 类型,取决于 episode 参数,其可能是 Human 或者 Droid 类型。在间接抉择的状况下,你只能申请 Character 上存在的字段,譬如 name。
如果要申请具体类型上的字段,你须要应用一个类型条件内联片段。因为第一个片段标注为 ... on Droid,primaryFunction 仅在 hero 返回的 Character 为 Droid 类型时才会执行。同理实用于 Human 类型的 height 字段。
具名片段也能够用于同样的状况,因为具名片段总是附带了一个类型。
元字段(Meta fields)
某些状况下,你并不知道你将从 GraphQL 服务取得什么类型,这时候你就须要一些办法在客户端来决定如何解决这些数据。GraphQL 容许你在查问的任何地位申请 __typename,一个元字段,以取得那个地位的对象类型名称。
// 申请{ search(text: "an") { __typename ... on Human { name } ... on Droid { name } ... on Starship { name } }}// 响应{ "data": { "search": [ { "__typename": "Human", "name": "Han Solo" }, { "__typename": "Human", "name": "Leia Organa" }, { "__typename": "Starship", "name": "TIE Advanced x1" } ] }}
下面的查问中,search 返回了一个联结类型,其可能是三种选项之一。没有 __typename 字段的状况下,简直不可能在客户端分辨开这三个不同的类型。
参考资料:
https://graphql.cn/learn/quer...