GraphQL概述: 使用React前端框架創建一個 to-Do List API

本文由樂何在眾成翻譯平台翻譯。

設想你想要參考食譜烤一個蛋糕。你將需要一些原料,並且一些合適的量。如果你能拿一個盒子裝好你烘焙所需要的各種原料 ,並且已經稱量好匹配菜譜的份量,那肯定會讓烘焙更簡單。如果你把前端 UI設想成一塊蛋糕的話,那這就是GraphQL所做的事。

在本教程中我們將寫一個小的GraphQL server 來響應Todo List app的請求。你也可以 在眾多app中來挑選,但是這些日子我開始使用React做項目,所以我將會選擇React來做前端框架。不過,你也可以挑選你用得習慣的任何js框架。

GraphQL

GraphQL 允許我們定義 一個查詢來提供一個通用的介面在客戶端和服務端之間來請求和處理數據。它用一種查詢語言來處理,允許客戶端使用一種直觀和靈活的語法和來按照客戶端程序的設計和需求來構建和組裝數據。

這使客戶端從服務端 檢索數據更加的高效。舉個栗子,設想從一個 GraphQL的實例中, 客戶端除了title和id 其它的欄位一概不要,那麼這個模型應該是長這樣:

query Query {n todos {n id,n titlen }n}n

結果數據(JSON)是:

Which produces the resulting data (in JSON):

{n "data": {n "todos": [n {n "id": 1446412739542,n "title": "Read emails"n },n {n "id": 1446412740883,n "title": "Buy orange"n },n {n "id": 1446412741215,n "title": "Fix garbage"n }n ]n }n}n

大概我們的展示demo中沒有保存數據。這背後的原因是每次我們都啟動服務,在內存中存儲的Todo(s)數組變為空了。我們將在下面的內容中展示如何向數組中添加數據。

如你所見,返回的格式已經被替換成了客戶端已經定義和描述過了的查詢格式。就像文章「GraphQL 概述 – GraphQL 和 Node.js 入門 」中規定的。

GraphQL的查詢都像是沒有屬性的JSON對象,GraphQL 不是一種語言特性 這點被提到 很重要,它只是在客戶端和服務端中間的一種規範。如果使用通用的語言,任何的客戶端都能和任何服務端通信。

介紹 GraphQL.js

GraphQL.js 是一種基於js的GraphQL參考模型,它提供了兩個重要的功能:

  1. 創建一種類型的語法模型(schema)。
  2. 應該該類型的語法(schema)的查詢 。

需要創建一個匹配代碼基層的GraphQL 類型語法(schema)。在接下來的代碼中,我們定義一個簡單的語法(schema)。它有一種類型和一個匯總的Todo(s)列表(每個列表元素有含有三個欄位),額外的,它還提供了服務於該類型語法(schema)和查詢結果。

var graphql = require (graphql);nn// Here is some dummy data to make this piece of code simpler.n// It will be changeable after introducing mutation.nvar TODOs = [n {n "id": 1446412739542,n "title": "Read emails",n "completed": falsen },n {n "id": 1446412740883,n "title": "Buy orange",n "completed": truen }n];nnvar TodoType = new graphql.GraphQLObjectType({n name: todo,n fields: function () {n return {n id: {n type: graphql.GraphQLIntn },n title: {n type: graphql.GraphQLStringn },n completed: {n type: graphql.GraphQLBooleann }n }n }n});nnvar queryType = new graphql.GraphQLObjectType({n name: Query,n fields: function () {n return {n todos: {n type: new graphql.GraphQLList(TodoType),n resolve: function () {n return TODOs;n }n }n }n }n});nnmodule.exports = new graphql.GraphQLSchema({n query: queryTypen});n

讓我們現在看一下給我們一個JSON數據結果的js文件的代碼:

var graphql = require (graphql).graphqlnvar express = require(express)nvar graphQLHTTP = require(express-graphql)nvar Schema = require(./schema)nvar query = query { todos { id, title, completed } }nngraphql(Schema, query).then( function(result) {n console.log(JSON.stringify(result));n // Printsn // {n // "data":{n // "todos":[n // {n // "id":1446412739542,n // "title":"Read emails",n // "completed":falsen // },n // {n // "id":1446412740883,n // "title":"Buy orange",n // "completed":truen // }n // ]n // }n // }n});nnvar app = express()n .use(/, graphQLHTTP({ schema: Schema, pretty: true }))n .listen(8080, function (err) {n console.log(GraphQL Server is now running on localhost:8080);n });n

下面的代碼提供了跟上面同樣 的執行結果,cURL在本例中並非是強制執行來得到 更長遠的優勢 的。它只是一種不用在瀏覽器中擊中例子 來檢索數據的方式 。請注意萬一你是一個Windows 用戶, 你可以使用Windows的命令提示符來執行cURL例子,此外, 這裡你還可以找到好的資源來在你的系統里安裝cURL.

$ curl -XPOST -H "Content-Type:application/graphql" -d query { todos { title } } http://localhost:8080n{n "data": {n "todos": [n {n "title": "Read emails"n },n {n "title": "Buy orange"n }n ]n }n}n

關於語法(schema)的一個重要的事情 ,自從它描述了用戶可以使用的API,它就假定數據已經存儲 了。數據存儲和描述的方式是一種實現細節。

React

React 是由Facebook和Instagram來開發 的一種用來創建用戶界面 JavaScript 庫。很多人會認為React是MVC模型中的V, 官方文檔中是這樣規定的:

我們做出React是為了解決一個問題:創建大型應用時,載入數據超時。根源在於構建可重用的組件。實際上,本質就是構建組件庫。

如果你需要一個React指南,你可以閱讀下面的資料:

  • 視頻: React入門
  • React JS庫概述
  • 視頻: 單向數據流概述

一個簡單的React 組件

React 組件通過render()方法來獲取輸入數據並將返回結果渲染展示。這裡是使用JSX(跟XML語法相似)的例子. JSX是一個非必須項。JSX是一種更像是XML的JavaScript 語法擴展,你可以使用React將簡單的JSX語法轉化。

輸入數據可以通過this.props來向render()渲染的組件傳值。下面是關於如何創建一個React 組件的簡單的例子 並且在 CodePen中可用.

var Application = React.createClass({n render: function() {n return n { this.props.text }n { this.props.id }n ;n }n});n

和適當的這些預編譯的代碼,這些未編譯過的JavaScript代碼由JSX編譯器生成。

"use strict";nvar Application = React.createClass({n displayName: "Application",n render: function render() {n return React.createElement(n "div",n null,n this.props.text,n this.props.idn );n }n});n

如果你想探究更多關於React 組件,可以花一分鐘 看一下這個視頻關於組件狀態的介紹.

一次關於本例子的綵排

首先,我的們需要 一個服務端 (運行正常的)來接收我們從Todo List應用發出的GraphQL請求。這個服務端已經在上面寫好了。

開啟我們的服務,在命令行中執行:

$ git clone https://github.com/sitepoint-editors/todo-graphql-server.gitn$ cd todo-graphql-servern$ npm installn$ npm startn

你必須已經安裝Node v4.0.0以其更高的版本,因為服務端的代碼 使用了在老版本中並不支持的ES2015 特性 。

任何以/graphql結尾的POST請求 將會與我們的GraphQL語法(schema)發生執行衝突。測試一下是否正常運行,輸入以下 代碼 :

$ curl -XPOST -H "Content-Type:application/graphql" -d query { todos { title } } http://localhost:8080n{n "data": {n "todos": []n }n}n

還是沒有數據保存。所以我們每次重啟服務,在內存中的存儲了todo(s) 數組數據都會被清空。當然 ,我們不單單想只讀空數組,我們還需要添加和更新數據。這種接收異常類型的操作,在GraphQL中被 稱作修改(mutations),定義一個修改(mutations)跟定義一個查詢一樣,也會返回一個類型的的值。這個想法是無論什麼變數發生了變化 ,就返回什麼。

var MutationAdd = {n type: new GraphQLList(TodoType),n description: Add a Todo,n args: {n title: {n name: Todo title,n type: new GraphQLNonNull(GraphQLString)n }n },n resolve: (root, {title}) => {n TODOs.push({n id: (new Date()).getTime(),n title: title,n completed: falsen });n return TODOs;n }n};nnvar MutationType = new GraphQLObjectType({n name: Mutation,n fields: {n add: MutationAddn }n});nnexport var Schema = new GraphQLSchema({n query: QueryType,n mutation: MutationTypen});n

上面的箭頭符號 (=>) 參考定義函數的新語法, ES2015中最有趣的部分之一。

正如Clay Allsopp所寫的這篇題為「Your First GraphQL Server」 文章中所寫,

修改(mutation)與查詢之間的一個有意義的區別是轉換是串列的,但是查詢沒有這樣的規定(實際上,GraphQL鼓勵服務端為獨立查詢開發固有的並行模型)。GraphQL說明書提供 了這個關於修改(mutation)查詢的一個集合例子必須按照下面的順序在服務端執行:

{n first: changeTheNumber(newNumber: 1) {n theNumbern },n second: changeTheNumber(newNumber: 3) {n theNumbern },n third: changeTheNumber(newNumber: 2) {n theNumbern }n}n

因此,在請求結束, theNumber 欄位值一定是2。在這個快速的修改(mutation)的介紹之後,我們可以最終在服務端添加一個todo 。

$ curl -XPOST -H "Content-Type:application/graphql" -d mutation { add (title: "Clean garage") { id, title } } http://localhost:8080n{n "data": {n "add": [n {n "id": 1446443172937,n "title": "Clean garage"n }n ]n }n}n

是不是相當的酷?我們除了這個添加(add)修改還有更多的修改(mutation):toggle, toggleAll, destroy, clearCompleted,和save。一個值得注意的事是我們在所有的修改中傳遞參數,所以有的欄位都 可接收參數。追加參數是相當簡單,並且它們都可以被resolve函數捕獲。

今天的結尾,我們有兩種類型的查詢:

  • 一種是從服務端取數據(get);
  • 另一種是操作創建, 更新, 刪除(create, update, delete)數據。

服務正常運行後,我們已經準備好來用我們基於React的Todo List了。 React TodoMVC例子一個分支就像本文一開始提到 的那樣,下載,並執行:

$ git clone -b react-graphql https://github.com/sitepoint-editors/todomvc.gitn$ cd todomvcn$ npm installn$ node server.jsn

瀏覽器中輸入地址http://localhost:3000來運行應用。這個代碼對比之前的版本有兩個主要的變更。首先,服務端的TodoModel已經被修改了。

第二,我們本地創建了一個服務端代理來直接使用GraphQL 請求我們創建的服務。 更多的細節 ,查看下面的圖片。

而且,你能 在這 找到一個demo。

總結

如你在本文所看到 的,GraphQL和GraphQL.js是Facebook在2015年最新發布的開源技術 ,它核心的想法是 UI知道組件需要渲染的數據的詳細集合。

作者:Igor Ribeiro Lima

原 文:GraphQL Overview: Build a to-Do List API with a React Front-End

譯 文:眾成翻譯

作 者:樂何 譯

更多文章:SDK.CN - 中國領先的開發者服務平台

熱門資訊:

  • GraphQL概述: 使用React前端框架創建一個 to-Do List API
  • 如何找出並打包文件成 tar 包
  • PyTorch一周年戰績總結:是否比TensorFlow來勢兇猛?
  • Mysql 索引你了解多少?
  • RisingStack 2017年最流行的Nod

推薦閱讀:

如何評價 Meteor 的替代品 Meatier?
relay學習

TAG:GraphQL | React | 前端框架 |