一、GraphQL介绍
1.1 简介
GraphQL 是一种新的 API 的查询语言,它提供了一种更高效、强大和灵活 API 查询。它 是由 Facebook 开发和开源,目前由来自世界各地的大公司和个人维护。GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且 没有任何冗余。它弥补了 RESTful API(字段冗余,扩展性差、无法聚合 api、无法定义数据 类型、网络请求次数多)等不足
注意:GraphQL 是 api 的查询语言,而不是数据库。从这个意义上说,它是数据库无关的, 而且可以在使用 API 的任何环境中有效使用,我们可以理解为 GraphQL 是基于 API 之上的一 层封装,目的是为了更好,更灵活的适用于业务的需求变化
GraphQL 可以用在常见各种服务器端语言以及客户端语言中
服务器端语言:C# / .NET、Clojure、Elixir、Erlang、Go、Groovy、Java、JavaScript、PHP、Python、 Scala、Ruby
客户端语言:js、React + React Native、Angular、Vue.js、Apollo Link、Native iOS、Native Android、 Scala.js
中文文档:http://graphql.cn
GraphQL 出现的历史背景
当提起API设计的时候,大家通常会想到SOAP(一种简单的基于 XML 的协议),RESTful 等设计方式,从 2000 年 RESTful 的理论被提出的时候,在业界引起了很大反响,因为这种 设计理念更易于用户的使用,所以便很快的被大家所接受。
我们知道 REST 是一种从服务 器公开数据的流行方式。当 REST 的概念被提及出来时,客户端应用程序对数据的需求相 对简单,而开发的速度并没有达到今天的水平。
因此 REST 对于许多应用程序来说是非常 适合的。然而在业务越发复杂,客户对系统的扩展性有了更高的要求时,API 环境发生了巨 大的变,RESTful 显得心有余而力不足。比如:字段冗余,扩展性差、无法聚合 api、无法 定义数据类型、网络请求次数多
GraphQL 的出现整好弥补了 RESTful APi 的不足
使用 GraphQL 的公司
目前已经有很多的公司在使用 GraphQL(https://graphql.org/users/)

1.2 为什么推荐 GraphQL 而不是 RESTful API
在过去的十多年中,REST 已经成为设计 web api 的标准(虽然只是一个模糊的标准)。
它提供了一些很棒的想法,比如无状态服务器和结构化的资源访问。
然而 REST api 表 现得过于僵化,无法跟上访问它们的客户的快速变化的需求
RESTful API 不足
- 扩展性(多个终端需要返回不同的字段),单个 RESTful 接口返回数据越来越 臃肿。前端对于真正用到的字段是没有直观映像的,仅仅通过 url 地址,无法预测也无 法回忆返回的字段数目和字段是否有效,接口返回 50 个字段,但却只用 5 个字段,造 成字段冗余,扩展性差,单个 RESTful 接口返回数据越来越臃肿
- API 聚合问题,某个前端展现,实际需要调用多个独立的 RESTful API 才能获 取到足够的数据,导致网络请求次数多
- 前后端字段频繁改动,导致类型不一致,错误的数据类型可能会导致网站出错 尤其是在业务多变的场景中,很难在保证工程质量的同时快速满足业务需求
GraphQL 的优点
- 吸收了 RESTful API 的特性
- 所见即所得 各种不同的前端框架和平台可以指定自己需要的字段。查询的返回结果就是输 入的查询结构的精确映射
客户端可以自定义 Api 聚合
如果设计的数据结构是从属的,直接就能在查询语句中指定;即使数据结构是独 立的,也可以在查询语句中指定上下文,只需要一次网络请求,就能获得资源和子 资源的数据。
代码即是文档
GraphQL 会把 schema 定义和相关的注释生成可视化的文档,从而使得代码的变更,直接就反映到最新的文档上,避免 RESTful 中手工维护可能会造成代码、 文档不一致的问题
参数类型强校验
- RESTful 方案本身没有对参数的类型做规定,往往都需要自行实现参数的校验机制, 以确保安全。
- 但 GraphQL 提供了强类型的 schema 机制,从而天然确保了参数类型的合法性
二、GraphQl类型系统
2.1 GraphQl类型
可以将GraphQL的类型系统分为
标量类型(ScalarTypes,标量类型)和其他高级数据类型,标量类型即可以表示最细粒度数据结构的数据类型,可以和JavaScript的原始类型对应
GraphQL规范目前规定支持的标量类型有
- Int:有符号
32位整数 –GraphQLInt - Float:有符号双精度浮点值 –
GraphQLFloat - String:
UTF‐8字符序列 –GraphQLString - Boolean:
true或者false–GraphQLBoolean - ID(GraphQLID):ID标量类型表示一个唯一标识符,通常用以重新获取对象或者作为缓存中的键。ID类型使用和String一样的方式序列化;然而将其定义为ID意味着并不需要可读型。
GraphQL其他高级数据类型包括
- Object:对象(newGraphQLObjectType)
用于描述层级或者树形数据结构。对于树形数据结构来说,叶子字段的类型都是标量数据类型。几乎所有GraphQL类型都是对象类型。Object类型有一个name字段,以及一个很重要的fields字段。fields字段可以描述出一个完整的数据结构。例如一个表示地址数据结构的GraphQL对象为
const AddressType=newGraphQLObjectType({ |
Interface:接口用于描述多个类型的通用字Union:联合类型用于描述某个字段能够支持的所有返回类型以及具体请求真正的返回类型Enum:枚举用于表示可枚举数据结构的类型InputObject:输入对象List:列表
列表是其他类型的封装,通常用于对象字段的描述。例如下面PersonType类型数据的parents和children字段
const PersonType=newGraphQLObjectType({ |
Non-Null:不能为Null
Non-Null强制类型的值不能为null,并且在请求出错时一定会报错。可以用于必须保证值不能为null的字段。例如数据库的行的id字段不能为null
const RowType=newGraphQLObjectType({ |
2.2 GraphQl查询语言
GraphQL规范支持两种操作
query:仅获取数据(fetch)的只读请求mutation:获取数据后还有写操作的请求
新版本的GraphQL还支持
subscription,这是为了处理订阅更新这种比较复杂的实时数据更新场景而设计的操作

三、Express中集成GraphQl 实现 Server API
3.1 安装mongodb造数据
使用mongodb做数据库演示,mac安装mongodb,brew install mongodb-community
# 进入mongo shell |
或者导入数据库数据
下载数据库文件解压并导入mongodb即可 https://blog.poetries.top/db/koa.zip
导入mongodb数据库
mongorestore -h localhost:27017 -d koa-demo(数据库名称,不存在会自动创建) ./dump(本地数据文件路径) |
3.2 express集成GraphQl
https://github.com/graphql/express-graphql
npm install express-graphql graphql--save |
引入express-graphql配置中间件
app完善配置
// app.js |
定义GraphQLSchema模型
- 新建
schema/default.js - 定义
Schema
const DB=require('../model/db.js'); /*引入DB库*/ |
编写数据库操作方法
/** |
打开本地调试

四、Koa中集成GraphQl实现 Server API
下载数据库文件解压并导入mongodb即可 https://blog.poetries.top/db/koa.zip
- 导入mongodb数据库
mongorestore -h localhost:27017 -d koa-demo(数据库名称,不存在会自动创建) ./dump(本地数据文件路径) - 导出mongodb数据库
mongodump -h localhost:27017 -d test(数据库名称) -o ./dump
npm install graphql koa-graphql koa-mount --save |
实现导航列表API、文章分类API、文章列表API、文章详情API 、文章列表分页查询API、以及文章列表关联文章分类实现聚合API
4.1 app完善配置
// app.js |
4.2 定义schema模型
// schema/default.js |
4.3 编写数据库操作方法
// model/db.js |
启动服务


4.4 聚合查询
聚合查询文章分类信息,分类信息的方式要放在article的schema里面,这样才能聚合查询到

聚合查询结果

查询订单,聚合查询订单关联的商品信息返回,实现类似以下效果

// schema/default.js |

查询订单详情

需要哪些字段,就返回哪些字段,编辑器会自定提示

4.5 分页查询
//定义文章分类的schema |
4.6 实现数据增加、修改、删除
// scehma/default.js |
- 新增

可以看到必填字段不填会提示

再次查询列表

- 修改

- 删除

五、Vue中使用GraphQl
5.1 使用graphQl简单查询
安装
- 找到Vue中集成GraphQl的文档
- 安装相应的模块
ApolloBoost是一种零配置开始使用ApolloClient的方式。它包含一些实用的默认值,例如我们推荐的InMemoryCache和HttpLink,它非常适合用于快速启动开发。将它与vue-apollo和graphql一起安装:
npm install vue-apollo graphql apollo-boost --save |
- 在
src/main.js中引入apollo-boost模块并实例化ApolloClient
import ApolloClient from'apollo-boost' |
可以打开 http://118.123.14.36:3002/graphql 在控制台查看查询结果

- 在
src/main.js配置vue-apollo插件
import VueApollofrom'vue-apollo' |
- 创建
Apollo provider
Provider保存了可以在接下来被所有子组件使用的Apollo客户端实例
const apolloProvider = newVueApollo({ |
使用apollo Provider选项将它添加到你的应用程序
new Vue({ |
简单查询
组件加载的时候就会去服务器请求数据,请求的数据会放在
navList这个属性上面,在模板中可以直接使用当前属性
import gql from'graphql-tag'; |
另一种写法:
import gql from 'graphql-tag'; |
完整例子
<template> |
高级查询
<div class="news"> |
逻辑
import gql from 'graphql-tag'; |
Vue GraphQl 传参查询
<template> |
5.2 使用graphQl增加修改删除
服务器端接口

<template> |

可以看到新增成功效果

5.3 上拉分页加载更多
npm i vue-infinite-scroll -S |
// main.js配置 |
方法1:数据拼接
<template> |
方法2:使用 fetchMore 实现分页(推荐)
https://vue-apollo.netlify.app/zh-cn/guide/apollo/pagination.html
<template> |
分页效果

项目例子完整代码下载地址 https://blog.poetries.top/assets/graphql-code.zip
六、文档
- 中文文档:http://graphql.cn
- Github: https://github.com/facebook/graphql
- vue-apollo文档:https://vue-apollo.netlify.app/zh-cn/guide/apollo.html