GraphQL 是什么
Facebook 开发的一种数据查询语言
GraphQL 使用 Schema 来描述数据,并通过制定和实现 GraphQL 规范定义了支持 Schema 查询的 DSQL (Domain Specific Query Language,领域特定查询语言,由 FACEBOOK 提出。
特点
- 请求需要的数据,不多不少,只取得需要的字段
- 获取多个资源,只用一个请求
- 描述所有可能类型的系统。便于维护,根据需求平滑演进,添加或者隐藏字段。
GraphQL 和 Restful 对比
- Restful 一个接口只能返回一个资源,GraphQL 一次可以获取多个资源。
- Restful 用不同的 url 来区分资源,GraphQL 用类型区分资源。
实例
const express = require('express');
const { buildSchema } = require('graphql');
const grapqlHTTP = require('express-graphql');
// 定义 schema,查询和类型
const schema = buildSchema(`
type Query {
hello: String,
accountName: String,
}
`);
// 定义查询对应的处理器
const root = {
hello() {
return 'hello world';
},
accountName() {
return '张三';
}
};
const app = express();
app.use('/graphql', grapqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}));
app.listen(3000);
基本参数类型
基本数据类型:String、Int、Float、Boolean、ID,都可以在 shema 声明。
参数传递
- 和 JavaScript 传递参数一样,小括号内定义形参,但是注意:参数需要定义类型。
- !(叹号)代表参数不能为空。
type Query {
rollDice(numDice: Int!, numSides: Int): [Int]
}
const express = require('express');
const { buildSchema } = require('graphql');
const grapqlHTTP = require('express-graphql');
// 定义 schema,查询和类型
const schema = buildSchema(`
type Query {
getClassMates(classNo:Int!): [String]
}
`);
// 定义查询对应的处理器
const root = {
getClassMates({ classNo }) {
const obj = {
32: ['小明', '小李', '小鱼'],
61: ['大三', '大力', '大开'],
};
return obj[classNo];
}
};
const app = express();
app.use('/graphql', grapqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}));
app.listen(3000);
自定义参数类型
const express = require('express');
const { buildSchema } = require('graphql');
const grapqlHTTP = require('express-graphql');
// 定义 schema,查询和类型
const schema = buildSchema(`
type Account {
name: String
age: Int
sex: String
department: String
salary(city: String): Int
}
type Query {
getClassMates(classNo: Int!): [String]
account(username: String): Account
}
`);
// 定义查询对应的处理器
const root = {
getClassMates({ classNo }) {
const obj = {
32: ['小明', '小李', '小鱼'],
61: ['大三', '大力', '大开'],
};
return obj[classNo];
},
account({ username }) {
const name = username;
const sex = '男';
const age = 18;
const department = '开发部';
const salary = ({ city }) => {
if( city === '上海' ) {
return 10000;
}
return 4000;
};
return {
name,
age,
sex,
department,
salary
}
}
};
const app = express();
app.use('/graphql', grapqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}));
app.listen(3000);
前端调用 GraphQL 接口
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>graphqQL</title>
</head>
<body>
<button id="getQuery">获取数据</button>
<script>
const button = document.querySelector('#getQuery');
button.addEventListener('click',() => {
const query = `
query Account($username: String) {
account(username: $username) {
name
age
sex
salary(city: "北京")
}
}
`;
const variables = { username: '李大四' };
fetch('/graphql', {
method: 'post',
headers: {
'Content-Type': 'application/json',
'Accent': 'application/json',
},
body: JSON.stringify({
query,
variables,
})
}).then(res=>res.json)
.catch(e=>{
console.log(e);
})
});
</script>
</body>
</html>
helloGraphQL.js
const express = require('express');
const { buildSchema } = require('graphql');
const grapqlHTTP = require('express-graphql');
// 定义 schema,查询和类型
const schema = buildSchema(`
type Account {
name: String
age: Int
sex: String
department: String
salary(city: String): Int
}
type Query {
getClassMates(classNo: Int!): [String]
account(username: String): Account
}
`);
// 定义查询对应的处理器
const root = {
getClassMates({ classNo }) {
const obj = {
32: ['小明', '小李', '小鱼'],
61: ['大三', '大力', '大开'],
};
return obj[classNo];
},
account({ username }) {
const name = username;
const sex = '男';
const age = 18;
const department = '开发部';
const salary = ({ city }) => {
if( city === '上海' ) {
return 10000;
}
return 4000;
};
return {
name,
age,
sex,
department,
salary
}
}
};
const app = express();
app.use('/graphql', grapqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}));
app.use(express.static('public'));
app.listen(3000);
Mutation
const express = require('express');
const { buildSchema } = require('graphql');
const grapqlHTTP = require('express-graphql');
// 定义 schema,查询和类型
const schema = buildSchema(`
input AccountInput {
name: String
age: Int
sex: String
department: String
}
type Account {
name: String
age: Int
sex: String
department: String
}
type Mutation {
createAccount(input: AccountInput): Account
updateAccount(id: ID!, input: AccountInput): Account
}
type Query {
account: [Account]
}
`);
const fakeDB = {};
// 定义查询对应的处理器
const root = {
accounts(){
var arr = [];
for (let key in fakeDB) {
arr.push(fakeDB[key]);
}
return arr;
},
createAccount({ input }) {
// 相当于数据库的保存
fakeDB[input.name] = input;
return fakeDB[input.name]
},
updateAccount({ id, input }) {
// 相当于数据库的更新
Object.assign({}, fakeDB[id], input);
fakeDB[id] = updateAccount;
return updateAccount;
}
};
const app = express();
app.use('/graphql', grapqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}));
app.listen(3000);
与数据库结合使用
参考
【1】GraphQL-js 中文网
【2】解析 GraphQL 的查询语法【译】| 前端外刊评论
【3】GraphQL 从入门到实践
【4】GraphQL 入门到精通(视频)
【5】GraghQL初探(一) | 奇舞周刊
【8】GraphQL 学习:Github GraphQL API v4 初探
【9】搭建你的第一个 GraphQL 服务器
【10】GraphQL-前端开发的利剑与桥梁