本文由乐何在众成翻译平台翻译.
设想你想要参考食谱烤一个蛋糕.你将需要一些原料,并且一些合适的量.如果你能拿一个盒子装好你烘焙所需要的各种原料 ,并且已经称量好匹配菜谱的份量,那肯定会让烘焙更简单.如果你把前端 UI 设想成一块蛋糕的话,那这就是 GraphQL 所做的事.
在本教程中我们将写一个小的 GraphQL server 来响应 Todo List app 的请求.你也可以 在 众多 app 中来挑选,但是这些日子我开始使用 React 做项目,所以我将会选择 React 来做前端框架.不过,你也可以挑选你用得习惯的任何 js 框架.
GraphQL
GraphQL 允许我们定义 一个查询来提供一个通用的接口在客户端和服务端之间来请求和处理数据.它用一种查询语言来处理,允许客户端使用一种 直观和灵活的语法 和来按照客户端程序的设计和需求来构建和组装数据.
这使客户端从服务端 检索数据更加的高效.举个栗子,设想从一个 GraphQL 的实例 中, 客户端除了 title 和 id 其它的字段一概不要,那么这个模型应该是长这样:
query Query {
todos {
id,
title
}
}
结果数据(JSON)是:
Which produces the resulting data (in JSON):
{
"data": {
"todos": [
{
"id": 1446412739542,
"title": "Read emails"
},
{
"id": 1446412740883,
"title": "Buy orange"
},
{
"id": 1446412741215,
"title": "Fix garbage"
}
]
}
}
大概我们的展示 demo 中没有保存数据.这背后的原因是每次我们都启动服务,在内存中存储的 Todo(s) 数组变为空了.我们将在下面的内容中展示如何向数组中添加数据.
如你所见,返回的格式已经被替换成了客户端已经定义和描述过了的查询格式.就像文章 "GraphQL 概述 - GraphQL 和 Node.js 入门" 中规定的.
GraphQL 的查询都像是没有属性的 JSON 对象,GraphQL 不是一种语言特性 这点被提到 很重要,它只是在客户端和服务端中间的一种规范.如果使用通用的语言,任何的客户端都能和任何服务端通信.
介绍 GraphQL.js
GraphQL.js 是一种基于 js 的 GraphQL 参考模型,它提供了两个重要的功能:
创建一种类型的语法模型 (schema).
应该该类型的语法 (schema) 的查询 .
需要创建一个匹配代码基层的 GraphQL 类型语法 (schema).在接下来的代码中,我们定义一个简单的语法(schema).它有一种类型和一个汇总的 Todo(s) 列表(每个列表元素有含有三个字段),额外的,它还提供了服务于该类型语法 (schema) 和查询结果.
var graphql = require('graphql');
// Here is some dummy data to make this piece of code simpler.
// It will be changeable after introducing mutation.
var TODOs = [{
"id": 1446412739542,
"title": "Read emails",
"completed": false
},
{
"id": 1446412740883,
"title": "Buy orange",
"completed": true
}];
var TodoType = new graphql.GraphQLObjectType({
name: 'todo',
fields: function() {
return {
id: {
type: graphql.GraphQLInt
},
title: {
type: graphql.GraphQLString
},
completed: {
type: graphql.GraphQLBoolean
}
}
}
});
var queryType = new graphql.GraphQLObjectType({
name: 'Query',
fields: function() {
return {
todos: {
type: new graphql.GraphQLList(TodoType),
resolve: function() {
return TODOs;
}
}
}
}
});
module.exports = new graphql.GraphQLSchema({
query: queryType
});
让我们现在看一下给我们一个 JSON 数据结果的 js 文件的代码:
var graphql = require('graphql').graphql
var express = require('express') var graphQLHTTP = require('express-graphql') var Schema = require('./schema') var query = 'query { todos { id, title, completed } }'graphql(Schema, query).then(function(result) {
console.log(JSON.stringify(result));
// Prints
// {
// "data":{
// "todos":[
// {
// "id":1446412739542,
// "title":"Read emails",
// "completed":false
// },
// {
// "id":1446412740883,
// "title":"Buy orange",
// "completed":true
// }
// ]
// }
// }
});
var app = express().use('/', graphQLHTTP({
schema: Schema,
pretty: true
})).listen(8080,
function(err) {
console.log('GraphQL Server is now running on localhost:8080');
});
下面的代码提供了跟上面同样 的执行结果,cURL 在本例中并非是强制执行来得到 更长远的优势 的.它只是一种不用在浏览器中击中 例子 来检索数据的方式 .请注意万一你是一个 Windows 用户, 你可以使用 Windows 的命令提示符来执行 cURL 例子 , 此外, 这里你还可以找到好的资源来在你的系统里安装 cURL .
$ curl -XPOST -H "Content-Type:application/graphql" -d 'query { todos { title } }' http://localhost:8080
{
"data": {
"todos": [
{
"title": "Read emails"
},
{
"title": "Buy orange"
}
]
}
}
关于语法 (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({
render: function() {
return
{ this.props.text }
{ this.props.id }
;
}
});
和适当的这些预编译的代码,这些未编译过的 JavaScript 代码由 JSX 编译器生成.
"use strict";
var Application = React.createClass({
displayName: "Application",
render: function render() {
return React.createElement(
"div",
null,
this.props.text,
this.props.id
);
}
});
如果你想探究更多关于 React 组件,可以花一分钟 看一下这个视频 关于组件状态的介绍 .
一次关于本例子的彩排
首先,我的们需要 一个服务端 (运行正常的) 来接收我们从 Todo List 应用发出的 GraphQL 请求.这个服务端已经在上面写好了.
开启我们的服务,在命令行中执行:
$ git clone https://github.com/sitepoint-editors/todo-graphql-server.git
$ cd todo-graphql-server
$ npm install
$ npm start
你必须已经安装 Node v4.0.0 以其更高的版本,因为服务端的代码 使用了在老版本中并不支持的 ES2015 特性 .
任何以 / graphql 结尾的 POST 请求 将会与我们的 GraphQL 语法 (schema) 发生执行冲突.测试一下是否正常运行,输入以下 代码 :
$ curl - XPOST - H "Content-Type:application/graphql" - d 'query { todos { title } }'http: //localhost:8080
{
"data": {
"todos": []
}
}
还是没有数据保存.所以我们每次重启服务,在内存中的存储了 todo(s) 数组数据都会被清空.当然 ,我们不单单想只读空数组,我们还需要添加和更新数据.这种接收异常类型的操作,在 GraphQL 中被 称作修改(mutations),定义一个修改 (mutations) 跟定义一个查询一样,也会返回一个类型的的值.这个想法是无论什么变量发生了变化 ,就返回什么.
var MutationAdd = {
type: new GraphQLList(TodoType),
description: 'Add a Todo',
args: {
title: {
name: 'Todo title',
type: new GraphQLNonNull(GraphQLString)
}
},
resolve: (root, {title}) => {
TODOs.push({
id: (new Date()).getTime(),
title: title,
completed: false
});
return TODOs;
}
};
var MutationType = new GraphQLObjectType({
name: 'Mutation',
fields: {
add: MutationAdd
}
});
export var Schema = new GraphQLSchema({
query: QueryType,
mutation: MutationType
});
上面的箭头符号 (=>) 参考 定义函数的新语法 , ES2015 中最有趣的部分之一.
正如 Clay Allsopp 所写的这篇题为 "Your First GraphQL Server" 文章中所写,
修改(mutation)与查询之间的一个有意义的区别是转换是串行的,但是查询没有这样的规定(实际上,GraphQL 鼓励服务端为独立查询开发固有的并行模型).GraphQL 说明书提供 了这个关于修改(mutation)查询的一个集合例子必须按照下面的顺序在服务端执行:
{
first: changeTheNumber(newNumber: 1) {
theNumber
},
second: changeTheNumber(newNumber: 3) {
theNumber
},
third: changeTheNumber(newNumber: 2) {
theNumber
}
}
因此,在请求结束, theNumber 字段值一定是 2.在这个快速的修改(mutation)的介绍之后,我们可以最终在服务端添加一个 todo .
$ curl -XPOST -H "Content-Type:application/graphql" -d 'mutation { add (title: "Clean garage") { id, title } }' http://localhost:8080
{
"data": {
"add": [
{
"id": 1446443172937,
"title": "Clean garage"
}
]
}
}
是不是相当的酷?我们除了这个添加 (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.git
$ cd todomvc
$ npm install
$ node server.js
浏览器中输入地址 http://localhost:3000 来运行应用.这个代码对比 之前的版本 有两个主要的变更.首先,服务端的 TodoModel 已经被修改了.
第二,我们本地创建了一个服务端代理来直接使用 GraphQL 请求我们创建的服务. 更多的细节 ,查看下面的图片.
而且,你能 在这 找到一个 demo.
总结
如你在本文所看到 的,GraphQL 和 GraphQL.js 是 Facebook 在 2015 年最新发布的开源技术 ,它核心的想法是 UI 知道组件需要渲染的数据的详细集合.
来源: https://sdk.cn/news/8031