簡介
- GraphQL是一個用于API的查詢語言捉兴,一個使用基于類型系統(tǒng)來執(zhí)行查詢的服務(wù)端運(yùn)行時
- GraphQL未與任何特定數(shù)據(jù)庫尚粘,存儲引擎綁定庙睡,而是依靠現(xiàn)有代碼和數(shù)據(jù)支撐
查詢和變更
字段(Fields)
- GraphQL關(guān)于請求對象上的特定字段
- 查詢和查詢的結(jié)果擁有一致的數(shù)據(jù)結(jié)構(gòu)(很重要)
- 客戶端得到想要的數(shù)據(jù)
- 服務(wù)器準(zhǔn)確知道客戶端請求的字段
- 可以對對象字段進(jìn)行次級選擇
// 查詢
{
hero {
name
# 可以添加備注
friends {
name
}
}
}
// 結(jié)果
{
"data" : {
"hero": {
"name": "wxy",
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
參數(shù)(Arguments)
- 每一個字段蹈矮,嵌套對象都能有自己的一組參數(shù)长已,使得GraphQL可以完美替代多次API獲取請求
- 可以給標(biāo)量(scalar)字段傳遞參數(shù)畜眨,GraphQL自帶一套默認(rèn)類型,也可以自己定制類型术瓮,來序列化輸出格式
Schema和類型
// 查詢
{
human(id: "1000") {
name
height
}
}
// 結(jié)果
{
"data": {
"human": {
"name": "Luke Skywalker",
"height": 1.72
}
}
}
別名(Aliases)
- 通過別名胶果,查詢相同字段的不同內(nèi)容
// 查詢不同的hero
{
empireHero: hero(episode: EMPIRE) {
name
}
jediHero: hero(episode: JEDI) {
name
}
}
// 通過別名,查詢不同的hero
{
"data": {
"empireHero": {
"name": "Luke Skywalker"
},
"jediHero": {
"name": "R2-D2"
}
}
}
片段(Fragments)
- GraphQL可復(fù)用單元斤斧,好的抽象早抠,可以避免重復(fù)代碼
{
leftComparison: hero(episode: EMPIRE) {
...comparisonFields
}
rightComparison: hero(episode: JEDI) {
...comparisonFields
}
}
fragment comparisonFields on Character {
name
appearsIn
friends {
name
}
}
// 結(jié)果
{
"data": {
"leftComparison": {
"name": "Luke Skywalker",
"appearsIn": [
"NEWHOPE",
"EMPIRE",
"JEDI"
],
"friends": [
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
},
{
"name": "C-3PO"
},
{
"name": "R2-D2"
}
]
},
"rightComparison": {
"name": "R2-D2",
"appearsIn": [
"NEWHOPE",
"EMPIRE",
"JEDI"
],
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
操作
一個操作query HeroNameAndFriends
- 操作類型關(guān)鍵字——描述打算做什么類型的操作
- query
- mutation
- subscription
- 操作名稱
HeroNameAndFriends
- 想象成函數(shù)名,有利于追蹤和調(diào)試
變量(Variables)
- 查詢參數(shù)可能是動態(tài)的撬讽,GraphQL擁有一級方法將動態(tài)值提取到查詢之外蕊连,然后作為分離的字典穿進(jìn)去悬垃。這些動態(tài)值,就是變量
- 如何使用變量
- 使用
$variableName
替代查詢中的靜態(tài)值 - 聲明
$variableName
為查詢接收的變量之一 - 將
variableName: value
通過傳輸轉(zhuǎn)用(通常是JSON)的分離的變量字典中甘苍。
- 使用
- 用法
// 聲明
query HeroNameAndFriends($episode: Episode) {
hero(episode: $episode) {
name
friends {
name
}
}
}
// 查詢
{
"episode": "JEDI"
}
// 結(jié)果
{
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
變量使用注意事項
- 變量前綴必須為
$
- 聲明變量后跟類型尝蠕,上例中是
Episode
- 所有聲明的變量都必須是:
- 標(biāo)量
- 枚舉值
- 輸入對象類型(與服務(wù)器有關(guān))
- 要傳遞一個復(fù)雜對象到一個字段上,必須知道服務(wù)器上匹配的類型载庭。
- 變量定義允許:
- 可選的
- 必要的看彼,在類型后加
!
變量默認(rèn)值
query HeroNameAndFriends($episode: Episode = "JEDI") {
hero(episode: $episode) {
name
friends {
name
}
}
}
指令(Directives)
- 指令可以附著在字段或者片段包含的字段上,以服務(wù)單期待的方式改變查詢的執(zhí)行囚聚。
- GraphQL核心規(guī)范的兩個指令:
-
@include(if: Boolean)
僅在參數(shù)為true
靖榕,包含被指令附著的字段 -
@skip(if: Boolean)
如果參數(shù)為true
,跳過被指令附著的字段
-
變更(Mutations)
- 用來變更服務(wù)器數(shù)據(jù)的方法
- 建議導(dǎo)致寫入的操作都應(yīng)該顯式的通過變更(mutation)來發(fā)送
- 提價變更同時也可以查詢變更后的對象顽铸。
// 聲明變更
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
createReview(episode: $ep, review: $review) {
stars
commentary
}
}
// 操作
{
"ep": "JEDI",
"review": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
// 變更后查詢結(jié)果
{
"data": {
"createReview": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
}
變更中的多個字段
- 查詢字段茁计,是并行查詢
- 變更字段,是線性執(zhí)行谓松,保證了變更不會出現(xiàn) 競爭的情況
內(nèi)聯(lián)片段(Inline Fragments)
- GraphQL schema 具備自定義接口和聯(lián)合類型的能力
- 若查詢的字段返回的是接口/聯(lián)合類型星压,就需要內(nèi)聯(lián)片段來去處下層具體類型的數(shù)據(jù)
//聲明
query HeroForEpisode($ep: Episode!) {
hero(episode: $ep) {
name
... on Droid {
primaryFunction
}
... on Human {
height
}
}
}
// 操作
{
"ep": "JEDI"
}
// 結(jié)果
{
"data": {
"hero": {
"name": "R2-D2",
"primaryFunction": "Astromech"
}
}
}
元字段(Meta fields)
- GraphQL允許在查詢的任何位置請求
__typename
,一個元字段鬼譬,以獲得那個位置的對象
// 聲明
{
search(text: "an") {
__typename
... on Human {
name
}
... on Droid {
name
}
... on Starship {
name
}
}
}
// 查詢結(jié)果
{
"data": {
"search": [
{
"__typename": "Human",
"name": "Han Solo"
},
{
"__typename": "Human",
"name": "Leia Organa"
},
{
"__typename": "Starship",
"name": "TIE Advanced x1"
}
]
}