從客戶端或前端的角度看,當我們提及 GraphQL 的核心概念時:
GraphQL文檔 (Document) 和 GraphQL操作 (Operation) 是兩大不可或缺的要素。
它們為開發者提供了一個與 GraphQL 伺服器互動的基礎。
本篇文章將先針對 GraphQL Document 深入探討:
透過對 GraphQL文檔 (Document) 的深入了解,開發者可以更靈活精確地描述他們所需的資料結構,從而提升整體的開發效率和資料交互的準確性。
GraphQL 請求字符串 (request string) 的內容被稱為 GraphQL Document,例如:
{
post {
id
title
body
}
}
這種語法使得 GraphQL 伺服器或客戶端能夠解析和驗證請求內容。
首先,讓我們瞭解這兩者的基本定義:
GraphQL Document:
GraphQL 查詢語法:
簡單來說,「GraphQL 查詢語法」可以視為一套撰寫指南或語言規範,而「GraphQL Document」則是基於這些規範所撰寫出的具體內容。因此,當開發者在編寫或解讀一份 GraphQL Document 時,實質上就是在實踐 GraphQL 查詢語法的應用。
以下是一份標準的 GraphQL Document,其中包含了查詢操作:
query {
post(id: 1) {
id
title
body
user {
id
name
email
}
}
}
事實上,GraphQL Document 是由多個元件所構成,且每個元件都有明確定義好的固定格式和用途。讓我們徐徐道來...
Field 在 GraphQL Document 中代表資料結構中的一個單位或屬性。
欄位描述了一段離散的資訊,這些資訊可以是簡單的,也可以是複雜的,且與資料之間存在關聯。
post:
id
。post
是此查詢的入口點,代表我們想要查詢的某篇文章。post
也是 Post
型別查詢的入口點
type Post {
id: ID!
title: String!
body: String
user: User
}
id, title, body: 這些都是 Field,且是 Post
型別下的屬性。它們分別代表文章的 ID、標題和內容。
user:
user
底下還有其他 Field,表示我們想要進一步查詢此使用者的某些屬性。user
可以被視為 Post 型別下的一個 Fielduser
也是 User
型別查詢的入口點
type User {
id: ID!
name: String!
email: String!
}
id, name, email: 這些都是 Field,且是 User
型別下的屬性。它們分別代表使用者的 ID、姓名和電子郵件地址。
以結論來說,在 GraphQL Document 中,所有的「名稱」(如 post
, id
, title
, body
, user
, name
, email
)都是 Field。根據它們在查詢中的位置和上下文,它們可以是主查詢的入口點,也可以是某個型別下的屬性,或是某個型別的關聯資訊。
在 GraphQL Document 中,當開發者想要指定一個特定的資料集或條件性的查詢時,可以使用參數來傳遞這些具體資訊給 GraphQL 查詢或變更。例如:
query {
post(id: 1) {
title
}
}
在上述查詢中,id: 1
就是傳遞給 post 查詢的一個參數,它告訴 GraphQL 伺服器:「我想要 ID 為 1 的文章的標題」。這裡的 id
是參數的名稱,而 1
是參數的值。
使用參數的好處包括:
在 GraphQL 中,Variables 允許我們將查詢中的動態值抽取出來,以獨立的方式提供,使得查詢本身保持靜態和可重用。這樣可以提高查詢的安全性,並讓查詢和變數的管理更加獨立。例如:
query GetPost($postId: ID!) {
post(id: $postId) {
id
title
}
}
在這裡,$postId
是一個變數,其型別被定義為 ID!
(表示非空的 ID 型別)。
當我們希望查詢特定的文章時,可以提供以下變數值:
{
"postId": "123"
}
這樣,查詢模板可以被重複使用,只需改變提供的變數值即可取得不同的文章。
Operation Name 在 GraphQL Document 中用來描述這次查詢或修改的「具體動作或目的」的名稱。
雖然命名對於單一請求來說不是必需的,但給予一個名稱往往非常有用。
舉例來說,在後台記錄或是除錯時,有命名可以更快速地知道這次操作的目的。特別是當一次請求中有好幾個操作時,有了操作名稱就可以清楚指出要執行哪一個。
例如,我們在同一個 GraphQL Document 中定義兩個操作,並給予它們明確的操作名稱:
query FetchPost {
post(id: 1) {
id
title
}
}
mutation UpdatePostContent {
updatePost(id: 1, content: "新的內容") {
id
content
}
}
在上述例子中,FetchPost
是 query 操作的名稱,而 UpdatePostContent
是 mutation 操作的名稱。
當我們希望執行其中一個操作時,可以使用其操作名稱來指定。
Aliases 在 GraphQL Document 中,是用來重新命名返回的字段名稱。當你在同一個查詢中多次使用同一個字段,但參數不同時,就可以透過別名來避免衝突。例如:
query {
userA: user(id: 1) {
name
}
userB: user(id: 2) {
name
}
}
在這裡,我們兩次查詢 user
但參數不同,透過使用 userA
和 userB
作為別名,可以同時獲得兩個不同的使用者名稱。
Fragments 在 GraphQL Document 中,是用來重複使用查詢中的部分字段集合。它可以幫助我們抽取共同的字段,使查詢結構更加清晰和模組化。例如:
fragment userInfo on User {
id
name
email
}
query {
userA: user(id: 1) {
...userInfo
}
userB: user(id: 2) {
...userInfo
}
}
在上述例子中,我們定義了一個名為 userInfo
的片段,並在兩次 user
查詢中重複使用它,避免了重複撰寫相同字段。這等同於:
query {
userA: user(id: 1) {
id
name
email
}
userB: user(id: 2) {
id
name
email
}
}
使用 Fragments 的好處,除了模組化與重用、結構清晰外,還可以有以下好處:
Directives 在 GraphQL 中是一種修飾符,用於動態地改變查詢的執行行為。它通常以 @
符號開頭,並可應用於字段、片段或整個查詢操作上。
舉例:常見的內建指令有 @include
和 @skip
,可以根據變數決定是否包含某字段。
query getUserInfo($withEmail: Boolean!) {
user {
id
name
email @include(if: $withEmail)
}
}
在這個例子中,只有當 $withEmail
變數為 true
時,email
字段才會被查詢。
有趣的是,Vue 有 Directives,GraphQL 也有 Directives,而這會不會在開發時造成混淆呢?
別著急,後續的篇章我們會深入探討這一點!
今日我們深入探索了 GraphQL Document 的核心概念,理解其在 GraphQL 中的角色和結構。它建立在強型別和契約驅動的基礎之上,保障了每一次查詢的精確性和一致性。而這,正是為何 GraphQL 能夠提供高效、可預期的查詢結果,也是 GraphQL 主要優勢。
明天,我們將繼續探討另一個核心概念:GraphQL操作 (Operation),我們將繼續揭開更多 GraphQL 的神秘面紗,敬請期待!