本文参考 intro-to-graphql 与 grapQL 官网 记录一次学习 graphQL 之旅。 项目API地址。
在学习语法时候,可以点开 Apollo playground进行实践。
文章目录
什么是GraphQL?
- 新的API标准、它由Facebook 2015年开源
- 声明式数据获取、并能够准确获取描述中的数据
- 强类型(类似 typescript)
- GraphQL服务公开单个端点并相应查询
- 可以与任何编程语言和框架一起使用
与 REST对比优势
- 数据的关联性和结构化更好
- 实现订阅问题
- 适应快速产品迭代,无版本API
- 对于后端请求的数据有更细致的了解
- 强类型系统定义API的功能
- 前端后端可以根据Schema共同开发
- 强大的开发工具
💡 要了解有关使用GraphQL的主要原因更多信息 click this
基本语法
- 字段
{
me{
name
avatar
githubLogin
inPhotos{
name
description
}
}
}
- 参数
{
User(login:4){
name
avatar
}
}
- 字段别名
{
User(login:4){
userName: name
avatar
}
}
返回结果如下:
{
"data": {
"User": {
"userName": "هستی نجاتی",
"avatar":"https://randomuser.me/api/portraits/thumb/women/50.jpg"
}
}
}
- 片段
片段允许重复使用常见的字段,从而减少了文档中的重复文本
Query noFragments{
me{
name
avatar
githubLogin
inPhotos{
name
description
postedBy{
name
avatar
githubLogin
}
}
}
}
使用 片段进行优化查询:
Query withFragments{
me{
...userInfo
inPhotos{
name
description
postedBy{
...userInfo
}
}
}
}
fragment userInfo on User{
name
avatar
githubLogin
}
- 变量
- 使用
$userID
代替查询中的静态值 - 将
$userID
传递给要查询的值 - 将
userID
作为请求体提交查询
- 使用
query getUser($userID:ID!){
User(login:$userID){
userName:name
}
}
- 指令
GraphQL 核心规范中目前包含两个指令:
- @include(if: Boolean) 仅在参数为 true 时,包含此字段。
- @skip(if: Boolean) 如果参数为 true,跳过此字段。
- 变更
mutation addUser{
addFakeUsers(count:1){
githubLogin
}
}
- 订阅
subscription{
newPhoto{
name
description
id
}
}
schema与类型
schema是类型的集合,类型表示自定义对象,它是用于描述从服务端查询到的数据。
为了方便定义类型,GraphQL引入了模版定义语言(Schema Definition Language,SDL)。它和 GraphQL 的查询语言很相似,让我们能够和 GraphQL schema 之间可以无语言差异地沟通。
- GraphQL内置的标量类型
- Int:有符号 32 位整数。
- Float:有符号双精度浮点值。
- String:UTF‐8 字符序列。
- Boolean:true 或者 false。
- ID:ID 标量类型表示一个唯一标识符,通常用以重新获取对象或者作为缓存中的键。ID 类型使用和 String 一样的方式序列化;然而将其定义为 ID 意味着并不需要人类可读型。
type Photo {
id: ID!
url: String!
name: String!
description: String
category: PhotoCategory! # 枚举类型
}
- 枚举类型
enum PhotoCategory {
SELFIE
PORTRAIT
ACTION
LANDSCAPE
GRAPHIC
}
- 自定义类型
scalar DateTime
type Photo{
...
created: DateTime!
}
也可以采用[graphql-custom-types]库,其中包含了很多自定义类型。
- 列表
列表通过使用方括号包裹GraphQL类型创建。
type User{
githubLogin: ID!
name: String
avatar: String
postedPhotos:[Photo!]!
inPhotos:[Photo!]!
}
列表声明 | 定义 | 无效实例 |
---|---|---|
[Int] | 可空的整数值列表 | 非整数 |
[Int!] | 不可空的整数值列表 | [1,null] |
[Int]! | 可空的整数值非空列表 | null |
[Int!]! | 不可空的整数值非空列表 | null、[null] |
- 联合类型
和TS类似,它也是用来返回几种不同类型之一。
union AgendaItem=StudyGroup| Workout
type StudyGroup{
name: String!
subject: String!
students: [User!]!
}
type Workout {
name:String!
reps:Int!
}
type Query{
agenda:[AgendaItem!]!
}
书写查询语句如下:
query schedule{
agenda{
...on Workout{
name
}
...on StudyGroup{
name
subject
students
}
}
}
- 接口
接口是一种抽象类型,它可以由对象类型实现。接口规范了Schema中的代码,确保了某些类型总是包含特定字段,无论它返回什么类型这些字段都是可查询的。
scalar DataTime
interface AgendaItem{
name: String!
start: DateTime!
end: DateTime!
}
type StudyGroup implements AgendaItem{
name: String!
start: DateTime!
end: DateTime!
topic: String
}
type Workout implements AgendaItem{
name: String!
start: DateTime!
end: DateTime!
reps: Int!
}
- 参数
通过loginId 查询某一个用户信息。
type Query{
User(login:ID!):User
}
- 输入类型
输入类型与GraphQL对象类型很相似,不过它仅仅是用于输入参数和规范输入参数。
input PostPhotoInput {
name: String!
category: PhotoCategory = SELFIE
description: String
}
type Mutation {
postPhoto(input: PostPhotoInput!): Photo!
}
- 订阅
subscription{
newPhoto{
name
description
}
}
- 返回类型
比如我们要使用gitHub授权(GitHub OAuth)登录时,当发送有效授权码进行身份验证。如果成功,我们将返回一个自定义类型该类型包含登录用户信息、以及token。
type AuthPayload {
token: String!
user: User!
}
type Mutation{
githubAuth(code:String!):AuthPayload!
}
- 订阅类型
我们添加一种订阅类型,通过它用户可以创建新的Photo或User类型。当发布照片时,新照片将推送给所有已订阅newPhoto的用户。
type Subscription {
newPhoto:Photo!
newUser: User!
}
- 查询与变更
type Query{
...
}
type Mutation{
...
}
客户端
使用 GraphQL Client 可以让我们专注于业务不用去关心网络请求、缓存等功能。
目前有两个主要的GraphQL客户端:
- Apollo Client:
它是由社区驱动开发,以处理缓存,更新UI等为目标构建客户端解决方案,目前包含React、Vue、Angular、ios和安卓系统的客户端包。 - Relay:是 Facebook在2015年开源。它囊括了生产中使用GraphQL所获得的一切,但是它仅兼容React和React-Native。
本文采用Apollo Client React
构建应用,起步流程参考官网
下面实现一个简单查询demo构建查询基本流程:
- 创建 应用 引入依赖
npx create-react-app photo-client --typescript
npm i @apollo/client graphql react