QL = Query Language,即查询语言。
GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。这是来自官方(http://graphql.cn/)的说明。
GraphQL的好处是请求你所要的数据。向你的 API 发出一个 GraphQL 请求就能准确获得你想要的数据,不多不少。 GraphQL 查询总是返回可预测的结果。使用 GraphQL 的应用可以工作得又快又稳,因为控制数据的是应用,而不是服务器。
另外只用一个请求就可以获取多个资源。GraphQL 查询不仅能够获得资源的属性,还能沿着资源间引用进一步查询。典型的 REST API 请求多个资源时得载入多个 URL,而 GraphQL 可以通过一次请求就获取你应用所需的所有数据。这样一来,即使是比较慢的移动网络连接下,使用 GraphQL 的应用也能表现得足够迅速。
首先,我们需要创建一个 GraphQL 服务可以接收查询和修改的验证和执行。
1)定义一个类型,描述服务能够进行数据查询:
import {
GraphQLObjectType,
GraphQLString,
GraphQLID,
GraphQLFloat,
} from 'graphql';
module.exports = new GraphQLObjectType({
name: 'Product',
fields: () => ({
ProductID: { type: GraphQLID },
ProductName: { type: GraphQLString },
UnitPrice: { type: GraphQLFloat },
UnitsInStock: { type: GraphQLFloat }
})
});
2)创建查询用于获取数据和修改服务器端数据:
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
products: {
type: new GraphQLList(Product),
resolve(parent, args){
return products;
}
}
}
});
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
AddProduct: {
type: Product,
args:{
ProductName: { type: new GraphQLNonNull(GraphQLString) },
UnitPrice: { type: new GraphQLNonNull(GraphQLFloat) },
UnitsInStock: { type: new GraphQLNonNull(GraphQLFloat) }
},
resolve(parent, args) {
let newProduct = {
ProductID: uuidv1(),
ProductName: args.ProductName,
UnitsInStock: args.UnitsInStock,
UnitPrice: args.UnitPrice
}
products.unshift(newProduct);
return newProduct;
}
},
UpdateProduct: {
type: Product,
args:{
ProductID: { type: new GraphQLNonNull(GraphQLID) },
ProductName: { type: new GraphQLNonNull(GraphQLString) },
UnitPrice: { type: new GraphQLNonNull(GraphQLFloat) },
UnitsInStock: { type: new GraphQLNonNull(GraphQLFloat) }
},
resolve(parent, args) {
let index = products.findIndex(product => product.ProductID == args.ProductID);
let product = products[index];
product.ProductName = args.ProductName;
product.UnitsInStock = args.UnitsInStock;
product.UnitPrice = args.UnitPrice;
return product;
}
},
DeleteProduct: {
type: Product,
args:{
ProductID: { type: new GraphQLNonNull(GraphQLID) }
},
resolve(parent, args) {
let index = products.findIndex(product => product.ProductID == args.ProductID);
products.splice(index, 1);
return { ProductID: args.ProductID };
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation
});
3)通过一个端点经HTTP提供GraphQL服务
import express from 'express';
import cors from 'cors';
import graphqlHTTP from 'express-graphql';
import schema from './schema';
import { createServer } from 'http';
const PORT = 3021;
var app = express();
app.use(cors());
app.use('/graphql', graphqlHTTP({
schema
}));
const server = createServer(app);
server.listen(PORT, () => {
console.log(`API Server is now running on http://localhost:${PORT}/graphql`)
});
为能够使用 Kendo UI Grid ,在客户端引入需要的资源。
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.2.620/styles/kendo.default-v2.min.css" />
<script src="http://kendo.cdn.telerik.com/2018.2.620/js/jquery.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2018.2.620/js/kendo.all.min.js"></script>
作为容器将 Grid 元素增加到页面,然后用 JavaScript 初始化部件。
<div id="content">
<div id="grid"></div>
</div>
$(document).ready(function() {
$("#grid").kendoGrid({
dataSource: dataSource,
height: 550,
groupable: true,
sortable: true,
pageable: true,
toolbar: ["create"],
editable: "inline",
columns: [{
field: "ProductID",
title: "Product ID"
},
{
field: "ProductName",
title: "Product Name"
},
{
field: "UnitPrice",
title: "Unit Price"
},
{
field: "UnitsInStock",
title: "Units in stock"
},
{
command: ["edit", "destroy"],
title: "Options ",
width: "250px"
}]
});
});
</script>
数据源提供丰富的配置选项允许您轻松地将其集成到 GraphQL API中,并与网格组件绑定。
编写查询和变更
GraphQL 请求对象上特定的字段,为初始化填充Grid,我们需要对API发出一个查询并返回对象类型。
<script>
var READ_PRODUCTS_QUERY = "query {" +
"products { ProductID, ProductName, UnitPrice, UnitsInStock }" +
"}";
</script>
然后创建更改的adding
, updating
和deleting
对象类型。
<script>
var ADD_PRODUCT_QUERY = "mutation AddProduct($ProductName: String!, $UnitPrice: Float!, $UnitsInStock: Float!){" +
"AddProduct(ProductName: $ProductName, UnitPrice: $UnitPrice, UnitsInStock: $UnitsInStock ){" +
"ProductID,"+
"ProductName,"+
"UnitPrice,"+
"UnitsInStock"+
"}"+
"}";
var UPDATE_PRODUCT_QUERY = "mutation UpdateProduct($ProductID: ID!, $ProductName: String! ,$UnitPrice: Float!, $UnitsInStock: Float!){" +
"UpdateProduct(ProductID: $ProductID, ProductName: $ProductName, UnitPrice: $UnitPrice, UnitsInStock: $UnitsInStock){" +
"ProductID," +
"ProductName," +
"UnitPrice," +
"UnitsInStock" +
"}" +
"}";
var DELETE_PRODUCT_QUERY = "mutation DeleteProduct($ProductID: ID!){" +
"DeleteProduct(ProductID: $ProductID){" +
"ProductID" +
"}" +
"}";
</script>
使用 API
为通过GraphQL查询或更改请求或修改数据,您所要做的就是配置透明读取DataSource的方法。
content-type
为 “application/json.”<script>
var dataSource = new kendo.data.DataSource({
pageSize: 20,
transport: {
read: {
contentType: "application/json",
url: "http://localhost:3021/graphql",
type: "POST",
data: function() {
return { query: READ_PRODUCTS_QUERY };
}
},
update: {
contentType: "application/json",
url: "http://localhost:3021/graphql",
type: "POST",
data: function(model) {
return {
query: UPDATE_PRODUCT_QUERY,
variables: model
};
}
},
destroy: {
contentType: "application/json",
url: "http://localhost:3021/graphql",
type: "POST",
data: function(model) {
return {
query: DELETE_PRODUCT_QUERY,
variables: model
};
}
},
create: {
contentType: "application/json",
url: "http://localhost:3021/graphql",
type: "POST",
data: function(model) {
return {
query: ADD_PRODUCT_QUERY,
variables: model
};
}
},
parameterMap: function(options, operation) {
return kendo.stringify(options);
}
},
schema: {
data: function(response) {
var data = response.data;
if(data.products) {
return data.products;
} else if(data.AddProduct) {
return data.AddProduct;
} else if(data.UpdateProduct) {
return data.UpdateProduct;
} else if(data.DeleteProduct){
return data.DeleteProduct;
}
},
model: {
id: "ProductID",
fields: {
ProductID: { type: "string", editable: false },
ProductName: { type: "string" },
UnitPrice: { type: "number" },
UnitsInStock: { type: "number" }
}
}
}
});
</script>
格式化请求参数和解析返回的数据
除了配置传输外,数据源的其他特性,如参数映射parameterMap()和模式选项,对于编码请求参数和解析API响应都是有用的:
在这里,通过简单地设置数据源,我们得到了采用 GraphQL API 的可运行的 Grid 例子。从这里开始,您可以开始探索Grid的大量功能,也可体验其他70多个可用的 Kendo UI 组件,并很容易地将它们绑定到GraphQL 服务。