GraphQL类型
GraphQL 的类型系统分为标量类型
和其他高级数据类型
。
1、标量类型
一个对象类型有自己的名字和字段,而某些时候,这些字段必然会解析到具体数据。这就是标量类型的来源:它们表示对应 GraphQL 查询的叶子节点。
标量类型可表示的数据类型,和 JavaScript 的原始类型对应。
标量类型
:String、Int、Float、Boolean、Enum、ID
Int
:有符号 32 位整数。Float
:有符号双精度浮点值。String
:UTF‐8 字符序列。Boolean
:true 或者 false。ID
:ID 标量类型表示一个唯一标识符。通常用以重新获取对象或者作为缓存中的键。ID 类型使用和 String 一样的方式序列化;然而将其定义为 ID 意味着并不需要人类可读型。enum
: 定义枚举。枚举类型是一种特殊的标量,它限制在一个特殊的可选值集合内。
好处:- 验证这个类型的任何参数是可选值的的某一个
- 与类型系统沟通,一个字段总是一个有限值集合的其中一个值。
下面是一个用 GraphQL schema 语言表示的 enum 定义:
这表示无论我们在 schema 的哪处使用了 Episode,都可以肯定它返回的是 onedemo、twodemo 和 threedemo 之一。enum Episode { onedemo twodemo threedemo }
2、高级数据类型
-
对象类型 (Object)
通过对象模型来构建GraphQL中关于一个数据模型的形状,同时还可以声明各个模型之间的内在关联(一对多、一对一或多对多)。
-
类型修饰符(Type Modifier)
类型系统仅仅只有类型定义是不够的,我们还需要对类型进行更广泛性的描述。类型修饰符就是用来修饰类型,以达到额外的数据类型要求控制。
例如
:
- 列表:[Type]
- 非空:Type!
- 列表非空:[Type]!
- 非空列表,列表内容类型非空:[Type!]!
在描述数据模型(模式Schema)时,就可以对字段施加限制条件。
例如定义了一个名为User的对象类型,并对其字段进行定义和施加限制条件:
返回数据时,像下面这种情况就是不允许的:
下面这样的数据就是正确的:
- 输入类型(Input Types)
输入对象看上去和常规对象一模一样,除了关键字是 input 而不是 type。更新数据时有用,与常规对象只有关键字修饰不一样,常规对象时用 type 修饰,输入类型用 input 修饰。
比如定义了一个输入类型:
前端发送变更请求时就可以使用(通过参数来指定输入的类型):
数组
数组类型
:[类型]
。例如:[Int]代表的是整型数组。数组定义起来会有些特殊。
- arr:[Int!] 如果写成 arr:[ ] 就会报错, 也就是说必须把数组里面的类型定义完全。
- Query里面的返回值必须严格按照type里面定义的返回, 不然也会报错。
const schema = buildSchema(`
type Query {
getClassMates(classNo:Int!):[String]
}
` );
//定义查询对应的resolver,也就是查询对应的处理器
const root = {
getClassMates({ classNo }) {
const obj = {
31: ['张三', '李四', '王五'],
61: ['张大三', '李大四', '王大五']
}
return obj[classNo];
}
}
我们对getClassMates
发起请求:
query {
getClassMates(classNo:31)
}
由于这里的数组是必传字段,如果不传参数的话,就会报错。
参数传递
GraphQL 对象类型上的每一个字段都可能有零个或者多个参数,它传递的所有参数都是具名的,不像 JavaScript 中,函数接受一个有序参数列表。而在 GraphQL 中,所有参数必须具名传递。例如下面的 length 字段:
length 字段定义了一个参数,unit。它和js传递参数一样,在小括号内定义形参,但是要注意:参数需要定义类型。 同时也需要注意:参数是必选还是可选的。当一个参数是可选的,我们可以定义一个默认值 —— 如果 unit 参数没有传递,那么它将会被默认设置为 METER。
包含参数的请求
const schema = buildSchema(`
type Account {
name:String
age:Int
sex:String
department:String
salary(city:String):Int
}
type Query {
account(username:String):Account
}
` );
//定义查询对应的resolver,也就是查询对应的处理器
const root = {
account({ username }) {
const name = username;
const sex = 'man';
const age = 18;
const department = '开发部';
const salary = ({ city }) => {
if (city === '广州' || city === '北京' || city === '上海') {
return 'big'
}
return 'small';
}
return {
name,
sex,
age,
department,
salary
}
}
}
我们在graphql中对account
进行请求:
query {
account(username:"李四") {
name
age
department
salary(city:"北京")
}
}
在客户端中访问graphql的接口
- 在文件夹根目录下创建pubic文件夹,然后创建index.html。
- 在server.js中使用
app.use(express.static('public'))
将public文件夹公开出去。 - 在index.html中使用fetch进行请求。
<button onclick="getData()">获取数据</button>
<script>
function getData() {
//由于account是个自定义类型,因此在这里至少要写一个子字段
const query = `
query Account($username: String){
account(username: $username){
name
age
sex
salary(city: "北京")
}
}
`
const vailables = {username:'李大四'}
fetch('/graphql',{
method:'POST',
headers:{
'Content-Type':'application/json',
'Accept':'application/json'
},
body:JSON.stringify({
query:query,
variables:vailables
})
}).then(res => res.json())
.then(data => {
console.log(data);
})
}
</script>
- 点击按钮之后,就会获取数据。