- 前置知识传送门 GraphQL入门
四. 客户端开发
4.1 基本查询
按需获取需要的数据
// 定义类型
const typeDefs = gql`
type Hero {
name: String
age: Int
}
# 查询类型
type Query {
hero: Hero
}
`;
// resolver 函数
const resolvers = {
Query: {
hero: () => {
return {
name: 'nordon',
age: 18
}
}
},
};
复制代码
// 查询 hero 对象的 name 属性
{
hero {
name
}
}
// 结果
{
"data": {
"hero": {
"name": "nordon"
}
}
}
复制代码
- 注意事项
- GraphQL 只有一个utl地址、客户端查询的所有信息都通过该地址获取数据
- 可以更具需要按照实际的需求获取特定的数据
4.2 操作名称
有多个操作时、操作名称是必须的、为了调试方便最好添加操作名
- 规则 — 操作类型 操作名称(操作名称自定义)
- 操作类型主要有两种
- query 用于查询
- mutation 用于数据变更 — CRUD
# 定义数据类型
const typeDefs = gql`
# 输入类型
input UserInfo {
name: String
pwd: String
}
# 用户类型
type User {
id: ID
name: String
pwd: String
}
# 变更类型
type Mutation {
addUser(userInfo: UserInfo): User
}
# 查询类型
type Query {
hello: String
msg: String
}
`;
// 3. 解析数据类型对应的具体数据
const resolvers = {
Query: {
hello: () => 'hi query',
msg: () => 'msg query'
},
Mutation: {
addUser: (parent, args) => {
return {
id: uuid(),
name: args.userInfo.name,
pwd: args.userInfo.pwd
}
}
}
};
复制代码
# 需要定义 每个查询的类型名称、存在多个查询前面必须存在 query、
query helloInfo {
hello
}
query msgInfo {
msg
}
mutation addUser {
addUser(userInfo: {
name: "nordon",
pwd: "123123"
}){
id
name
pwd
}
}
复制代码
01.png
- 注意事项
- 推荐所有的查询和变更操作都添加操作名称
4.3 查询参数
有时候需要根据特定的条件查询数据、此时可以使用查询参数
const typeDefs = gql`
# 学生类型
type Student {
name: String
age: Int
gender: Boolean
}
# 查询类型
type Query {
hello: String
stu(id: Int, name: String): Student
}
`;
const resolvers = {
Query: {
hello: () => 'Hello world!',
stu: (parent, args) => {
let stu = null;
if(args.id === 1 && args.name === 'nordon'){
stu = {
name: 'norodn',
age: 18,
gender: true
}
}else {
stu = {
name: 'null',
age: 0,
gender: false
}
}
return stu
}
},
};
复制代码
query stu {
stu(id: 1, name: "nordon"){
name
age
gender
}
}
复制代码
02.png
- 注意事项
- 查询字段可以携带参数、并且可以携带多个参数、参数之间通过逗号隔开
4.4 变量
有时字段的参数需要动态提供、而不是固定的值、此时就可以使用变量、类似函数中的形参
// 定义数据类型
const typeDefs = gql`
# 课程类型
type Course {
cname: String
score: Float
}
# 学生类型
type Student {
id: ID
sname: String
age: Int
scores(num: Float): [Course]
}
# 查询类型
type Query {
stu(id: Int): Student
}
`;
// 解析数据类型对应的具体数据
const resolvers = {
Student: {
scores: (parent, args) => {
return parent.scores && parent.scores.filter(item => item.score > args.num)
}
},
Query: {
stu: (parent, args) => {
if(args.id === 1){
return {
id: uuid(),
sname: 'nordon',
age:18,
scores: [{
cname: '数学',
score: 66
},{
cname: '英语',
score: 55
},{
cname: '语文',
score: 77
}]
}
}else{
return {
id:0,
sname: 'null',
scores: null
}
}
}
},
};
复制代码
03.png
04.png
- 注意事项
- 变量类型必须是标量、枚举型、输入对象类型
- 变量可以有默认值 ($id: Int = 1)
4.5 指令
有时候查询的字段数量不是固定的、此时可以通过制定的方式进行控制
- 两个指令
@include(if: Boolean)
仅在参数为true
时包含此字段@skip(if: Boolean)
如果参数为true
时跳过此字段
// 定义数据类型
const typeDefs = gql`
# 学生类型
type Student {
id: ID
name: String
gender: Boolean
}
# 查询类型
type Query {
stu(id: Int): Student
}
`;
// 解析数据类型对应的具体数据
const resolvers = {
Query: {
stu: (parent, args) => {
if(args.id === 1){
return {
id: uuid(),
name: 'nordon',
gender: true
}
}else{
return {
id: uuid(),
name: 'wangyao',
gender: false
}
}
}
},
};
复制代码
# 如果指令使用的、需要显示的传递字段、需要在后面增加一个!叹号
query stu($id: Int, $gender: Boolean!){
stu(id: $id){
id
name
gender @include(if: $gender)
# gender @skip(if: $gender)
}
}
复制代码
05.png
06.png
- 注意事项
- 可以通过这两个指令动态的控制查询的字段数量
- 指令用到的变量定义时需要添加!叹号、强制必须提供该值
4.6别名
通过不同的参数来查询相同的字段信息、比如查询学生的数学和英语成绩
// 定义数据类型
// Query 类型是默认客户端查询的类型、并且该类型在服务端必须存在并且是唯一的
const typeDefs = gql`
# 课程类型
type Course {
cname: String
score: Float
}
# 学生类型
type Student {
id: ID
sname: String
age: Int
scores(cname: String): [Course]
}
# 查询类型
type Query {
stu: Student
}
`;
01.png
// 解析数据类型对应的具体数据
const resolvers = {
Student:{
scores: (parent, args) => {
if(args.cname === '数学' || args.cname === '语文'){
return parent.scores.filter(item => item.cname === args.cname)
}else{
return parent.scores
}
}
},
Query: {
stu: (parent, args) => {
return {
id: uuid(),
sname: 'nordon',
age:18,
scores: [{
cname: '数学',
score: 66
},{
cname: '英语',
score: 55
},{
cname: '语文',
score: 77
}]
}
}
},
};
复制代码
query stu{
stu{
id
sname
math: scores(cname: "数学"){
cname
score
},
china: scores(cname: "语文"){
cname
score
},
all: scores{
cname
score
}
}
}
复制代码
07.png
- 注意事项
- 可以通过别名的方式获取特定某几项数据(查询接口的数据格式相同)
4.7 变更
改变服务器数据需要用到mutation操作
// 2. 定义数据类型
// Query 类型是默认客户端查询的类型、并且该类型在服务端必须存在并且是唯一的
const typeDefs = gql`
#输入类型
input UserInfo {
uname: String
pwd: String
}
# 用户类型
type User {
id: ID
uname: String
pwd: String
}
# 变更类型
type Mutation {
addUserByParams(uname: String, pwd: String): User
addUserByInput(userInput: UserInfo): User
}
# 查询类型
type Query {
hello: String
}
`;
// 3. 解析数据类型对应的具体数据
const resolvers = {
Query: {
hello: () => 'Hello world!'
},
Mutation: {
addUserByParams: (parent, args) => {
return {
id: uuid(),
uname: args.uname,
pwd: args.pwd
}
},
addUserByInput: (parent, args) => {
return {
id: uuid(),
uname: args.userInput.uname,
pwd: args.userInput.pwd
}
}
}
};
复制代码
mutation addUserByParams {
addUserByParams(uname: "nordon", pwd: "123123"){
id
uname
pwd
}
}
mutation addUserByInput($userInput: UserInfo){
addUserByInput(userInput: $userInput){
id
uname
pwd
}
}
复制代码
08.png
- 注意事项
- 通过 mutation 关键字实现变更操作
- userInput 变量并非标量、而是一个输入类型
- 参数的传递可以通过普通参数、也可以使用输入类型、一般较为复杂的数据采用输入类型