摘要:最終代碼省略其他輸入類型用標(biāo)識查詢類型需要至少定義一個不要會不顯示查詢這里需要轉(zhuǎn)成數(shù)組因為前面定義了返回值是類型相當(dāng)于數(shù)據(jù)庫的添加操作相當(dāng)于數(shù)據(jù)庫的更新操作省略其他現(xiàn)在我們可以啟動服務(wù)器,在上測試下效果了。
看完復(fù)聯(lián)四,我整理了這份 GraphQL 入門教程,哈哈真香。。。
歡迎關(guān)注我的 個人主頁 && 個人博客 && 個人知識庫 && 微信公眾號“前端自習(xí)課”
首先有請阿爸鎮(zhèn)貼!哈哈哈,需要高清原圖的小伙伴可以 點我下載 阿爸無敵 。
下面開始本文內(nèi)容:
一、GraphQL介紹GraphQL 是 Facebook 開發(fā)的一種 API 的查詢語言,與 2015 年公開發(fā)布,是 REST API 的替代品。
GraphQL 既是一種用于 API 的查詢語言也是一個滿足你數(shù)據(jù)查詢的運(yùn)行時。 GraphQL 對你的 API 中的數(shù)據(jù)提供了一套易于理解的完整描述,使得客戶端能夠準(zhǔn)確地獲得它需要的數(shù)據(jù),而且沒有任何冗余,也讓 API 更容易地隨著時間推移而演進(jìn),還能用于構(gòu)建強(qiáng)大的開發(fā)者工具。
官網(wǎng): http://graphql.org/
中文網(wǎng): http://graphql.cn/
請求你所要的數(shù)據(jù),不多不少;
如:hero 中有 name, age, sex 等,可以只取得需要的字段。
獲取多個資源,只用一個請求;
典型的 REST API 請求多個資源時得載入多個 URL,而 GraphQL 可以通過一次請求就獲取你應(yīng)用所需的所有數(shù)據(jù)。這樣也能保證在較慢的移動網(wǎng)絡(luò)連接下,使用 GraphQL 的應(yīng)用也能表現(xiàn)得足夠迅速。
描述所有可能類型的系統(tǒng)。便于維護(hù),根據(jù)需求平滑演進(jìn),添加或隱藏字段;
GraphQL 使用類型來保證應(yīng)用只請求可能的數(shù)據(jù),還提供了清晰的輔助性錯誤信息。應(yīng)用可以使用類型,而避免編寫手動解析代碼。
2. 簡單案例這里先看下簡單案例,體驗下 GraphQL 的神奇之處(后面詳細(xì)介紹)。
我們這樣定義查詢語句:
query { hero }
然后得到的就是我們所要查詢的 hero 字段:
{ "data": { "hero": "I"m iron man" } }
這樣用起來,是不是更舒服呢?
二、GraphQL與restful對比 1. restful介紹全稱:Representational State Transfer 表屬性狀態(tài)轉(zhuǎn)移。
本質(zhì)上就是定義 uri ,通過 API 接口來取得資源。通用系統(tǒng)架構(gòu),不受語言限制。
例子: 餓了嗎接口。
如:接口 restapi/shopping/v3/restaurants?latitude=13 就是個典型的 restful 接口,定義資源 + 查詢條件。
restful 一個接口只能返回一個資源,GraphQL 一次可以獲取多個資源。
restful 用不同 url 來區(qū)分資源,GraphQL 用類型區(qū)分資源。
三、使用express構(gòu)建基本helloworld 1. 簡單案例首先創(chuàng)建一個文件夾 demo ,并初始化一個 package.json,安裝 express / graphql / express-graphql 依賴包:
npm init -y npm install express graphql express-graphql -S
新建一個 hello.js,引入文件:
const express = require("express") const { buildSchema } = require("graphql") const graphqlHTTP = require("express-graphql")
創(chuàng)建一個 schema 來定義查詢語句和類型,buildSchema() 方法需要傳入的參數(shù)是字符串類型,如下面的 hero 查詢字段,后面的 String 類型表示字段返回的數(shù)據(jù)類型:
const schema = buildSchema(` type Query { hero: String } `)
創(chuàng)建一個 root 處理器,處理對應(yīng)的查詢,這里的 hello 處理器對應(yīng)的是 schema 中的 hero 字段查詢的處理,這里直接返回 I"m iron man 的結(jié)果:
const root = { hero: () => { return "I"m iron man" } }
當(dāng)然,處理器中也可以是其他復(fù)雜操作,后面會介紹。
然后實例化 express ,并且將路由轉(zhuǎn)發(fā)給 graphqlHTTP 處理:
const app = express() app.use("/graphql", graphqlHTTP({ schema, rootValue: root, graphiql: true })) app.listen(3000)
graphqlHTTP 中的三個參數(shù)介紹:
schema:定義的查詢語句和類型
rootValue:處理對應(yīng)查詢的處理器
graphiql:是否開啟調(diào)試窗口,開發(fā)階段開啟,生產(chǎn)階段關(guān)閉
接下來運(yùn)行項目,在命令行中執(zhí)行 node hello.js,這里可以在 graphiql 上做調(diào)試,打開地址 localhost:3000/graphiql 就可以愉快的查詢了。
另外我們可以在 graphiql 界面右側(cè)打開 Docs 查看我們定義的所有字段和描述信息。
最終代碼:
const express = require("express") const { buildSchema } = require("graphql") const graphqlHTTP = require("express-graphql") // 構(gòu)建schema,這里定義查詢的語句和類型 const schema = buildSchema(` type Query { hero: String } `) // 定義查詢所對應(yīng)的 resolver,也就是查詢對應(yīng)的處理器 const root = { hero: () => { return "I"m iron man" } } const app = express() // 將路由轉(zhuǎn)發(fā)給 graphqlHTTP 處理 app.use("/graphql", graphqlHTTP({ schema: schema, rootValue: root, graphiql: true })) app.listen(3000)2. 自定義類型查詢
我們前面的查詢中,已經(jīng)將 hero 字段定義為 String 類型,但是常常開發(fā)中,我們又會碰到字段是多個類型,即字段也能指代對象類型(Object),比如一個 user 字段會有 name 、age 等字段,而 name 返回字符串類型,age 返回數(shù)值類型。
這時候,我們可以對這個對象的字段進(jìn)行次級選擇(sub-selection)。GraphQL 查詢能夠遍歷相關(guān)對象及其字段,使得客戶端可以一次請求查詢大量相關(guān)數(shù)據(jù),而不像傳統(tǒng) REST 架構(gòu)中那樣需要多次往返查詢。
我們可以新建一個查詢類型來定義 user 字段返回的類型:
const schema = buildSchema(` type User { # 查詢可以有備注! name: String age: Int } type Query { hero: String user: User } `)
在處理器中我們也要加上:
const root = { hero: () => { return "I"m iron man" }, user: () => { return { name: "leo", age: 18 } } }
這邊 Int/String 參數(shù)類型的問題,下一章介紹
四、參數(shù)類型和參數(shù)傳遞 1. 基本參數(shù)類型String, Int, Float, Boolean 和 ID,這些基本參數(shù)類型可以在 schema 聲明中直接使用。
Int:有符號 32 位整數(shù)。
Float:有符號雙精度浮點值。
String:UTF‐8 字符序列。
Boolean:true 或者 false。
ID:ID 標(biāo)量類型表示一個唯一標(biāo)識符,通常用以重新獲取對象或者作為緩存中的鍵。ID 類型使用和 String 一樣的方式序列化;然而將其定義為 ID 意味著并不需要人類可讀型。
另外,我們可以使用 [類型] 來表示一類數(shù)組,如:
[Int] 表示整型數(shù)組;
[String] 表示字符串型數(shù)組;
2. 參數(shù)傳遞使用方式和 JS 參數(shù)傳遞一樣,小括號內(nèi)定義形參,但是參數(shù)需要定義類型。
使用 ! 代表參數(shù)不能為空。
下面案例:參數(shù) teamName 是 String 類型,必須傳遞,而 number 參數(shù)也是 Int 類型,但是是非必須傳遞,最后輸出的結(jié)果也是 String 類型。
type Query { getHero(teamName: String!, number: Int): [String] }
下面一個案例:
//...省略其他 const schema = buildSchema(` type Query { getHero(teamName: String!): [String] } `) const root = { getHero: ({teamName}) => { // 這里的操作 實際開發(fā)中常常用在請求數(shù)據(jù)庫 const hero = { "三國": ["張飛", "劉備", "關(guān)羽"], "復(fù)仇者聯(lián)盟": ["鋼鐵俠", "美國隊長", "綠巨人"] } return hero[teamName] } } //...省略其他
這時候我們在 GraphiQL 上輸入查詢,就會得到 復(fù)仇者聯(lián)盟 的英雄數(shù)據(jù)了。
// 查詢 query { getHero(teamName:"復(fù)仇者聯(lián)盟") } // 結(jié)果 { "data": { "getHero": [ "鋼鐵俠", "美國隊長", "綠巨人" ] } }3. 自定義返回類型
在實際開發(fā)中,我們返回的數(shù)據(jù)類型可能是一個對象,對象中可能既有 Int 類型的屬性,也有 String 類型的值,等等,這里我們可以使用 自定義返回類型 來處理:
//...省略其他 const schema = buildSchema(` type Hero { name: String age: Int doSomething(thing: String): String } type Query { getSuperHero(heroName: String!): Hero } `) const root = { getSuperHero: ({heroName}) => { // 這里的操作 實際開發(fā)中常常用在請求數(shù)據(jù)庫 const name = heroName const age = 18 const doSomething = ({thing}) => { return `I"m ${name}, I"m ${thing} now` } return { name, age, doSomething } } } //...省略其他
這里指定了 getSuperHero 字段的返回類型是 Hero 類型,隨后在上面定義了 Hero。
其中 Hero 類型中的 doSomething也是可以傳遞指定類型參數(shù),并且指定返回類型。
下面看下輸出情況:
// 查詢 query { getSuperHero(heroName:"IronMan") { name age doSomething } } // 結(jié)果 { "data": { "getSuperHero": { "name": "IronMan", "age": 46, "doSomething": "I"m IronMan, I"m undefined now" } } }
這里也可以給 doSomething 傳遞參數(shù),就會獲取到不同結(jié)果:
// 查詢 query { getSuperHero(heroName:"IronMan") { name age doSomething(thing:"watching TV") } } // 結(jié)果 { "data": { "getSuperHero": { "name": "IronMan", "age": 46, "doSomething": "I"m IronMan, I"m watching TV now" } } }五、GraphQL客戶端
這一節(jié)我們學(xué)習(xí)如何在客戶端中訪問 graphql 的接口。
1. 后端定義接口我們先在后端將接口開發(fā)完成,這里跟前面差不多,但需要多一步,使用 express 向外暴露一個文件夾,供用戶訪問靜態(tài)資源文件:
這里直接使用前一節(jié)的代碼啦~
// index.js 開發(fā) graphql 接口 //...省略其他 const schema = buildSchema(` type Hero { name: String age: Int doSomething(thing: String): String } type Query { getSuperHero(heroName: String!): Hero } `) const root = { getSuperHero: ({heroName}) => { // 這里的操作 實際開發(fā)中常常用在請求數(shù)據(jù)庫 const name = heroName const age = 46 const doSomething = ({thing}) => { return `I"m ${name}, I"m ${thing} now` } return { name, age, doSomething } } } const app = express() app.use("/graphql", graphqlHTTP({ schema, rootValue: root, graphiql: true })) // 公開文件夾 使用戶訪問靜態(tài)資源 app.use(express.static("public")) app.listen(3000)
這樣我們就給前端頁面提供一個可以訪問靜態(tài)資源的功能。
這里還需要在根目錄創(chuàng)建一個 public 文件夾,并在文件夾中添加 index.html 文件,此時的目錄結(jié)構(gòu):
|-node_modules |-public |---index.html |-index.js |-package.json2. 前端頁面請求
然后給 index.html 添加按鈕和事件綁定:
這里的變量 query 是個字符串類型,定義查詢條件,在條件 GetSuperHero 中的參數(shù),需要用 $ 符號來標(biāo)識,并在實際查詢 getSuperHero 中,作為參數(shù)的參數(shù)類型設(shè)置進(jìn)來。
然后定義變量 variables ,指定屬性的值,之后通過 fetch 發(fā)起請求:
當(dāng)我們寫完以后,點擊 獲取數(shù)據(jù) 就會在控制臺打印下面的數(shù)據(jù):
{ "data":{ "getSuperHero":{ "name":"鋼鐵俠", "age":46, "doSomething": "I"m 鋼鐵俠, I"m watching TV now" } } }3. 注意點
請求中的 query 參數(shù)需要對照好有 $ 符號的變量。
查詢語句 query GetSuperHero($heroName: String) 里參數(shù) $heroName 中的 heroName ;
查詢語句 getSuperHero(heroName: $heroName) 里類型 $heroName 中的 heroName ;
變量 variables 中的 heroName 屬性;
這三個名稱需要一樣。
請求中需要將數(shù)據(jù)序列化操作。
body: JSON.stringify({ query, variables })六、使用Mutations修改數(shù)據(jù) 1. Mutation 使用
根據(jù)前面的學(xué)習(xí),我們知道,要做查詢操作,需要使用 Query 來聲明:
type Query { queryHero(heroName: String): String }
當(dāng)我們要做修改操作,需要用到的是 Mutation :
type Mutation { createHero(heroName: String): String }
如果 Mutation 中字段的形參是自定義類型,則類型需要用 input 標(biāo)識:
const schema = buildSchema(` # 輸入類型 用 input 標(biāo)識 input HeroInput { name: String age: Int } # 查詢類型 type Hero { name: String age: Int } type Mutation { createHero(heroName: String): Hero updateHero(heroName: String, hero: HeroInput): Hero } `)
注意下:這里需要至少定義一個 Query 不然 GraphiQL 會不顯示查詢:
type Query { hero: [Hero] }2. Mutation 使用案例
先創(chuàng)建一個 schema ,內(nèi)容為上一步【1. Mutation 使用】中定義的內(nèi)容,這里不重復(fù)寫。
然后模擬創(chuàng)建一個本地數(shù)據(jù)庫 localDb, 用于模擬存放添加的超級英雄數(shù)據(jù):
const localDb = {}
接下來聲明 root 實現(xiàn) schema 中的字段方法:
const root = { hero() { // 這里需要轉(zhuǎn)成數(shù)組 因為前面定義了返回值是 [Hero] 類型 let arr = [] for(const key in localDb){ arr.push(localDb[key]) } return arr }, createHero({ input }) { // 相當(dāng)于數(shù)據(jù)庫的添加操作 localDb[input.name] = input return localDb[input.name] }, updateHero({ id, input }) { // 相當(dāng)于數(shù)據(jù)庫的更新操作 const update = Object.assign({}, localDb[id], input) localDb[id] = update return update } }
最后配置 graphqlHTTP 方法和啟動服務(wù)器,這里就不多重復(fù)咯。
最終代碼:
//...省略其他 const schema = buildSchema(` # 輸入類型 用 input 標(biāo)識 input HeroInput { name: String age: Int } # 查詢類型 type Hero { name: String age: Int } type Mutation { createHero(input: HeroInput): Hero updateHero(id: ID!, input: HeroInput): Hero } # 需要至少定義一個 Query 不要GraphiQL會不顯示查詢 type Query { hero: [Hero] } `) const localDb = {} const root = { hero() { // 這里需要轉(zhuǎn)成數(shù)組 因為前面定義了返回值是 [Hero] 類型 let arr = [] for(const key in localDb){ arr.push(localDb[key]) } return arr }, createHero({ input }) { // 相當(dāng)于數(shù)據(jù)庫的添加操作 localDb[input.name] = input return localDb[input.name] }, updateHero({ id, input }) { // 相當(dāng)于數(shù)據(jù)庫的更新操作 const update = Object.assign({}, localDb[id], input) localDb[id] = update return update } } //...省略其他
現(xiàn)在我們可以啟動服務(wù)器,在 GraphiQL 上測試下效果了。
我們是使用 mutation 的 createHero 字段添加兩條數(shù)據(jù):
mutation { createHero(input: { name: "鋼鐵俠" age: 40 }){ name age } }
mutation { createHero(input: { name: "美國隊長" age: 41 }){ name age } }
然后使用 query 的 hero 字段查詢添加的結(jié)果:
query { hero { name age } }
這樣我們就獲取到剛才的添加結(jié)果:
{ "data": { "hero": [ { "name": "鋼鐵俠", "age": 40 }, { "name": "美國隊長", "age": 41 } ] } }
然后我們開始更新數(shù)據(jù),使用 mutation 的 updateHero 字段將 美國隊長 的 age 值修改為 18:
mutation { updateHero(id: "美國隊長", input: { age: 18 }){ age } }
再使用 query 的 hero 字段查詢下新的數(shù)據(jù),會發(fā)現(xiàn) 美國隊長 的 age 值已經(jīng)更新為 18:
{ "data": { "hero": [ { "name": "鋼鐵俠", "age": 40 }, { "name": "美國隊長", "age": 18 } ] } }七、認(rèn)證和中間件
我們知道,修改數(shù)據(jù)的接口不能讓所有人隨意訪問,所以需要添加權(quán)限認(rèn)證,讓有權(quán)限的人才可以訪問。
在 express 中,可以很簡單的使用中間件來將請求進(jìn)行攔截,將沒有權(quán)限的請求過濾并返回錯誤提示。
中間件實際上是一個函數(shù),在接口執(zhí)行之前,先攔截請求,再決定我們是否接著往下走,還是返回錯誤提示。
這在【六、使用Mutations修改數(shù)據(jù)】的最終代碼上,在添加這個中間件:
//... 省略其他 const app = express() const middleWare = (req, res, next) => { // 這里是簡單模擬權(quán)限 // 實際開發(fā)中 更多的是和后端進(jìn)行 token 交換來判斷權(quán)限 if(req.url.indexOf("/graphql") !== -1 && req.headers.cookie.indexOf("auth") === -1){ // 向客戶端返回一個錯誤信息 res.send(JSON.stringify({ err: "暫無權(quán)限" })) return } next() // 正常下一步 } // 注冊中間件 app.use(middleWare) //... 省略其他
這里的權(quán)限判斷,只是簡單模擬,實際開發(fā)中,更多的是和后端進(jìn)行 token 交換來判斷權(quán)限(或者其他形式)。
我們重啟服務(wù)器,打開 http://localhost:3000/graphql ,發(fā)現(xiàn)頁面提示錯誤了,因為 cookies 中沒有含有 auth 字符串。
如果這里提示 TypeError: Cannot read property "indexOf" of undefined ,可以先不用管,因為瀏覽器中沒有 cookies 的原因,其實前面的權(quán)限判斷邏輯需要根據(jù)具體業(yè)務(wù)場景判斷。
為了方便測試,我們在 chrome 瀏覽器控制臺的 application 下,手動設(shè)置一個含有 auth 字符串的一個 cookies ,只是測試使用哦。
設(shè)置完成后,我們就能正常進(jìn)入頁面。
八、ConstructingTypes在前面的介紹中,我們要創(chuàng)建一個 schema 都是使用 buildSchema 方法來定義,但我們也可以使用另外一種定義方式。
就是這里要學(xué)習(xí)使用的構(gòu)造函數(shù) graphql.GraphQLObjectType 定義,它有這么幾個優(yōu)點和缺點:
優(yōu)點:報錯提醒更直觀,結(jié)構(gòu)更清晰,更便于維護(hù)。
缺點:代碼量上升。
1. 定義type(類型)這里先將前面定義的 Hero 類型進(jìn)行改造:
const graphql = require("graphql") // 需要引入 const HeroType = new graphql.GraphQLObjectType({ name: "Hero", fields: { name:{ type: graphql.GraphQLString }, age:{ type: graphql.GraphQLInt }, } })
兩者區(qū)別在于:
區(qū)別 | buildSchema | graphql.GraphQLObjectType |
---|---|---|
參數(shù)類型 | 字符串 | 對象 |
類名 | 跟在 type 字符后面,這里是 type Hero | 在參數(shù)對象的 name 屬性上 |
屬性定義 | 定義在類型后,鍵值對形式 | 定義在參數(shù)對象 fields 屬性中,值為對象,每個屬性名為鍵名,值也是對象,其中 type 屬性的值為 graphql 中的屬性,下面會補(bǔ)充 |
補(bǔ)充:
fields 屬性中的子屬性的類型通常有:
graphql.GraphQLString
graphql.GraphQLInt
graphql.GraphQLBoolean
....
即在 GraphQL后面跟上基本類型名稱。
2. 定義query(查詢)定義查詢的時候,跟之前類似,可以參照下面對比圖理解,這里比較不同的是,多了個 resolve 的方法,這個方法是用來執(zhí)行處理查詢的邏輯,其實就是之前的 root 中的方法。
const QueryType = new graphql.GraphQLObjectType({ name: "Query", fields: { // 一個個查詢方法 getSuperHero: { type: HeroType, args: { heroName: { type: graphql.GraphQLString } }, // 方法實現(xiàn) 查詢的處理函數(shù) resolve: function(_, { heroName }){ const name = heroName const age = 18 return { name, age } } } } })3. 創(chuàng)建 schema
創(chuàng)建的時候只需實例化并且將參數(shù)傳入即可:
// step3 構(gòu)造 schema const schema = new graphql.GraphQLSchema({ query: QueryType})
最后使用也是和前面一樣:
const app = express() app.use("/graphql", graphqlHTTP({ schema, graphiql: true })) app.listen(3000)九、與數(shù)據(jù)庫結(jié)合實戰(zhàn)
我們試著使用前面所學(xué)的內(nèi)容,開發(fā)一個簡單的實踐項目:
通過 GraphiQL 頁面,往 Mongodb 中插入和更新數(shù)據(jù),主要用到【六、使用Mutations修改數(shù)據(jù)】章節(jié)的操作。
首先我們可以到 Mongodb 官網(wǎng) 選擇對應(yīng)平臺和版本下載安裝。
下載安裝步驟,可以參考 mongoDB下載、安裝和配置,這里就不多介紹喲~~
安裝完成后,我們打開兩個終端,分別執(zhí)行下面兩行命令:
// 終端1 啟動數(shù)據(jù)庫 mongod --dbpath c:leoappmongodbdatadb // 終端2 進(jìn)入數(shù)據(jù)庫命令行操作模式 mongo2. 連接數(shù)據(jù)庫,創(chuàng)建 Schema 和 Model
首先我們新建一個文件 db.js ,并 npm install mongoose 安裝 mongoose ,然后寫入下面代碼,實現(xiàn)連接數(shù)據(jù)庫:
const express = require("express") const { buildSchema } = require("graphql") const graphqlHTTP = require("express-graphql") const mongoose = require("mongoose") const DB_PATH = "mongodb://127.0.0.1:27017/hero_table" const connect = () => { // 連接數(shù)據(jù)庫 mongoose.connect(DB_PATH) // 連接斷開 mongoose.connection.on("disconnected", () => { mongoose.connect(DB_PATH) }) // 連接失敗 mongoose.connection.on("error", err => { console.error(err) }) // 連接成功 mongoose.connection.on("connected", async () => { console.log("Connected to MongoDB connected", DB_PATH) }) } connect()
然后創(chuàng)建 Schema 和 Model:
let HeroSchema = new mongoose.Schema({ name: String, age: Number }) let HeroModel = mongoose.model("hero",HeroSchema, "hero_table")3. 聲明查詢語句
這一步,還是先使用【六、使用Mutations修改數(shù)據(jù)】章節(jié)的操作邏輯,也就是先用字符串創(chuàng)建查詢,而不使用 GraphQLObjectType 創(chuàng)建:
const schema = buildSchema(` # 輸入類型 用 input 標(biāo)識 input HeroInput { name: String age: Int } # 查詢類型 type Hero { name: String age: Int } type Mutation { createHero(input: HeroInput): Hero updateHero(hero: String!, input: HeroInput): Hero } # 需要至少定義一個 Query 不要GraphiQL會不顯示查詢 type Query { hero: [Hero] } `)
這邊案例有稍作修改
4. 實現(xiàn)添加數(shù)據(jù)和更新數(shù)據(jù)的邏輯這邊處理添加數(shù)據(jù)和更新數(shù)據(jù)的邏輯,就要修改之前聲明的 root 的操作內(nèi)容了:
const root = { hero() { return new Promise( (resolve, reject) => { HeroModel.find((err, res) => { if(err) { reject(err) return } resolve(res) }) }) }, createHero({ input }) { // 實例化一個Model const { name, age } = input const params = new HeroModel({ name, age }) return new Promise( (resolve, reject) => { params.save((err, res) => { if(err) { reject(err) return } resolve(res) }) }) }, updateHero({ hero, input }) { const { age } = input return new Promise ((resolve, reject) => { HeroModel.update({name: hero}, {age}, (err, res) => { if(err) { reject(err) return } resolve(res) }) }) } }5. 模擬測試
最后我們在 GraphiQL 頁面上模擬測試一下,首先添加兩個英雄,鋼鐵俠和美國隊長,并設(shè)置他們的 age / name 屬性:
mutation { createHero(input: { name: "鋼鐵俠" age: 40 }){ name age } }
mutation { createHero(input: { name: "美國隊長" age: 20 }){ name age } }
頁面和接口沒有報錯,說明我們添加成功,數(shù)據(jù)庫中也有這兩條數(shù)據(jù)了:
在測試下查詢:
query { hero { name age } }
查詢也正常,接下來測試下更新,將美國隊長的 age 修改為 60:
mutation { updateHero(hero: "美國隊長", input: { age: 60 }){ age } }
到這一步,我們也算是將這個練習(xí)做完了。
總結(jié)GraphQL 是一種 API 的查詢語言,是 REST API 的替代品。
GraphQL 可以使用一個請求,獲取所有想要的數(shù)據(jù)。
創(chuàng)建查詢的方式有兩種:使用 buildSchema 或者 GraphQLObjectType。
查詢操作用 Query,修改操作用 Mutations。
查詢類型用 type ,輸入類型用 input。
其實 GraphQL 還是很簡單好用的呢~~~
本文首發(fā)在 pingan8787個人博客,如需轉(zhuǎn)載請保留個人介紹
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/109401.html
摘要:啟動服務(wù),并打開新窗口可簡寫創(chuàng)建新組件可簡寫創(chuàng)建新服務(wù)創(chuàng)建路由模塊其他另外還有很多的命令提供,詳細(xì)可以查閱官方文檔命令。引入路由模塊導(dǎo)出路由模塊的指令這里需要添加一個數(shù)組,并傳入,導(dǎo)出讓路由器的相關(guān)指令可以在中的組件中使用。 本文目錄 一、項目起步 二、編寫路由組件 三、編寫頁面組件 1.編寫單一組件 2.模擬數(shù)據(jù) 3.編寫主從組件 四、編寫服務(wù) 1.為什么需要服務(wù) 2....
摘要:編寫單一組件我們首先寫一個書本信息的組件,代碼如下單個課本像火焰像灰燼程姬知識點是一個的復(fù)寫器指令,就像中的和中的。寫到這里,看看我們項目,還是一樣正常在運(yùn)行,只是現(xiàn)在項目中組件分工更加明確了。 本文目錄 一、項目起步 二、編寫路由組件 三、編寫頁面組件 1.編寫單一組件 2.模擬數(shù)據(jù) 3.編寫主從組件 四、編寫服務(wù) 1.為什么需要服務(wù) 2.編寫服務(wù) 五、...
摘要:發(fā)布通過回調(diào)方法向發(fā)布事件。觀察者一個回調(diào)函數(shù)的集合,它知道如何去監(jiān)聽由提供的值。 本文目錄 一、項目起步 二、編寫路由組件 三、編寫頁面組件 1.編寫單一組件 2.模擬數(shù)據(jù) 3.編寫主從組件 四、編寫服務(wù) 1.為什么需要服務(wù) 2.編寫服務(wù) 五、引入RxJS 1.關(guān)于RxJS 2.引入RxJS 3.改造數(shù)據(jù)獲取方式 六、改造組件 1.添...
摘要:然后我們在父組件上添加事件監(jiān)聽,并傳入本地的在對應(yīng)的中添加方法再來,我們在子組件上多導(dǎo)入和,并添加修飾器和調(diào)用這樣就實現(xiàn)了我們父子組件之間的事件傳遞啦,現(xiàn)在我們的頁面還是正常運(yùn)行,并且刪除一條數(shù)據(jù)后,頁面數(shù)據(jù)會更新。 本文目錄 一、項目起步 二、編寫路由組件 三、編寫頁面組件 1.編寫單一組件 2.模擬數(shù)據(jù) 3.編寫主從組件 四、編寫服務(wù) 1.為什么需要服務(wù) ...
摘要:今天順便總結(jié)了下之前的一些經(jīng)驗,希望對大家的工作或者學(xué)習(xí)有一些幫助。老生常談的啥的就不多說了,簡單分享些插件和配置功能優(yōu)化,方便大家更省力地寫代碼。另外,的正規(guī)操作常用于服務(wù)端項目的發(fā)布,增加了不少靈活性,一下子解放了運(yùn)維大哥。 前端工程化這些事情現(xiàn)在已經(jīng)算是深入人心了,即便不清楚具體含義vue-cli creat-react-app之類的腳手架也幫助大家快速開發(fā)了不少項目。 今天順便...
閱讀 1556·2021-11-25 09:43
閱讀 2337·2019-08-30 15:55
閱讀 1468·2019-08-30 13:08
閱讀 2670·2019-08-29 10:59
閱讀 818·2019-08-29 10:54
閱讀 1585·2019-08-26 18:26
閱讀 2548·2019-08-26 13:44
閱讀 2656·2019-08-23 18:36