如何使用JavaScript 将数据网格绑定到 GraphQL 服务
前言
作为一名前端开发人员,GraphQL对于我们来说是令人难以置信的好用。它可以用来简化数据访问,这让我们的工作变得更加容易。
什么是 GraphQL?它是一个抽象层,位于任意数量的数据源之上,并为您提供一个简单的 API 来访问所有数据。
GraphQL 的美妙之处在于您可以准确定义要从服务器返回的数据以及您希望其格式化的方式。它还允许您通过单个请求从多个来源获取数据。 GraphQL 还使用类型系统来提供更好的错误检查和消息传递。
简单尝试
我们可以用一个demo网址来尝试感受一下GraphQL的魅力所在:https://demodata.grapecity.com/northwind/ui/graphql
我们用 Microsoft 的经典 Northwind 数据库进行测试。假设我们想要获取产品列表,但我们只需要产品 ID 和名称字段。我们的查询如下所示:
{
products {
productId
productName
}
}
这是我们的查询测试器中的结果:
GraphQL 就是这么简单!
实际使用
日常开发过程中我们可以用我们常用的JavaScript来直接操作GraphQL,并将自己想要的数据呈现在页面上,
我们可以参考这个简单的应用程序,我们将仅使用 fetch API 来调用 GraphQL 服务:https://stackblitz.com/edit/wijmo-with-graphql-lruhgx
当然我们也可以添加更多的字段,方便我们取获取其他自己想要的信息:
fetch("https://demodata.grapecity.com/northwind/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: JSON.stringify({
query:
"{ products { productId, productName, unitPrice, unitsInStock, unitsOnOrder, reorderLevel, discontinued, categoryId }}"
})
})
我们打开控制台可以看到返回的结果以及绑定的数据内容:
此时我们配合一些表格类的控件,便可以将这些数据很友好地渲染在页面上,这里我们以葡萄城公司的纯前端表格控件SpreadJS为例:
安装 Wijmo:
npm install @grapecity/spread-sheets
我们可以在app.Vue中添加以下模块
import Vue from "vue";
import '@grapecity/spread-sheets-resources-zh';
GC.Spread.Common.CultureManager.culture("zh-cn");
import '@grapecity/spread-sheets-vue'
import GC from '@grapecity/spread-sheets';
import './styles.css';
紧接着我们只需要建立数据的key和我们表格内区域的映射关系就能完美的展示需要的内容
var colInfos = [
{ name: "productId", displayName: "productId" },
{ name: "productName", displayName: "productName", size: 100 },
{ name: "unitPrice", displayName: "unitPrice", size: 80 },
{ name: "unitsInStock", displayName: "unitsInStock" },
{ name: "unitsOnOrder", displayName: "unitsOnOrder", size: 80 },
{ name: "reorderLevel", displayName: "reorderLevel", size: 80 },
{ name: "discontinued", displayName: "discontinued", cellType: new GC.Spread.Sheets.CellTypes.CheckBox(), size: 80 },
{ name: "categoryId", displayName: "categoryId", size: 100},
];
sheet.bindColumns(colInfos);
现在我们有了数据和展示的组件,我们可以将它们放在一起。在 fetch 调用之后,在 then()方法中转换为 JSON 并用结果填充我们的 sheet即可。
fetch("https://demodata.grapecity.com/northwind/graphql", {
...
})
.then(r => r.json())
.then(data => bindData(data));
function bindData(data) {
sheet.setDataSource(data.data.products);
}
我们的数据已经绑定到了工作表上,且这是一种双向绑定关系,因此一旦数据有变动,页面的表格内渲染的数据也会相应的变动!
这是我们的网格渲染时的样子:
只需要一点点代码,我们就可以得到一个绑定到 GraphQL 源的功能齐全的在线表格!当然除了GraphQL的强大以外,也不得不佩服SpreadJS对于数据渲染的便捷和可靠性。
如果您想自己尝试这个应用程序,这里有一个实例:https://demo.grapecity.com.cn/spreadjs/SpreadJSTutorial/features/data-binding/sheet-level-binding/vue
深入讨论
类别信息动态渲染
GraphQL 最有趣的功能之一是将许多不同的查询聚合到一个请求中。此功能可用于最大程度地减少与服务器的往返次数,从而提高应用程序的响应能力。当然,对服务器进行多次往返仍然是合适的,但这是一个非常实用的功能。
在我们的示例中,我们加载了产品。我们还获得了每个产品的类别ID,因为每个产品都与另一个数据集中的类别相关联。 而我们相应的信息中希望添加类别信息,并通过CategoryID 查找类别。 GraphQL 的一个很酷的事情是我们可以便可以在一个查询中加载产品和类别两类信息!
以下是一个查询扩展后的样子:
{
products {
productId
productName
unitPrice
unitsInStock
unitsOnOrder
reorderLevel
discontinued
categoryId
}
categories {
categoryId
categoryName
}
}
如果我们将其放入查询测试器中,我们可以看到现在得到两个数组(一个用于产品,另一个用于类别)
现在我们希望将产品的类别信息按照我们给定类别信息进行展示,我们可以借助SpreadJS的数据绑定功能中对列的单元格类型来实现这个需求:
var combo = new GC.Spread.Sheets.CellTypes.ComboBox();
combo
.items(data.data.categories)
.editorValueType(GC.Spread.Sheets.CellTypes.EditorValueType.value);
var colInfos = [
{ name: "productId", displayName: "productId" },
{ name: "productName", displayName: "productName", size: 100 },
{ name: "unitPrice", displayName: "unitPrice", size: 80 },
{ name: "unitsInStock", displayName: "unitsInStock" },
{ name: "unitsOnOrder", displayName: "unitsOnOrder", size: 80 },
{ name: "reorderLevel", displayName: "reorderLevel", size: 80 },
{ name: "discontinued", displayName: "discontinued", cellType: new GC.Spread.Sheets.CellTypes.CheckBox(), size: 80 },
{ name: "Category", displayName: "categoryId", cellType: combo, size: 100},
];
sheet.bindColumns(colInfos);
如此一来我们在页面上看到的就不是类别的ID了,而是类别的名称
格式化数据
对于测量计算行业的开发人员来说,对于数据的精确是有规定的,即使给的数据中不存在小数,但是页面上展示数据时也是需要格式化成规定的小数位,而对此我们只要在数据绑定时为列信息添加格式化的信息即可
这里我们可以将Price设置为两位小数为例,只要添加一条formatter参数即可:
var colInfos = [
{ name: "productId", displayName: "productId" },
{ name: "productName", displayName: "productName", size: 100 },
{ name: "Price", displayName: "unitPrice",formatter: "[$¥-804]#,##0.00", size: 80 },
{ name: "unitsInStock", displayName: "unitsInStock" },
{ name: "unitsOnOrder", displayName: "unitsOnOrder", size: 80 },
{ name: "reorderLevel", displayName: "reorderLevel", size: 80 },
{ name: "discontinued", displayName: "discontinued", cellType: new GC.Spread.Sheets.CellTypes.CheckBox(), size: 80 },
{ name: "categoryId", displayName: "categoryId", size: 100},
];
sheet.bindColumns(colInfos);
结果如下所示:
数据验证
我们要做的下一件事是向我们的应用程序添加验证。SpreadJS中数据验证是存在继承性的,上一行同一列的单元格存在数据验证,那么下一个行同一位置就会继承上一行的数据验证效果。
因此我们可以参考这篇学习指南来实现数据展示的同时按照我们设定的标准进行数据的验证:
spread.options.highlightInvalidData = true;
var dv = GC.Spread.Sheets.DataValidation.createNumberValidator(GC.Spread.Sheets.ConditionalFormatting.ComparisonOperators.greaterThan, "11");
dv.showInputMessage(true);
dv.inputMessage("Units too low and none on order!");
dv.inputTitle("tip");
activeSheet.setDataValidator(0, 4, 1,1,dv,GC.Spread.Sheets.SheetArea.viewport);
在此验证处理程序中,我们查看unitsInStock 以确定是否应订购新单位。我们确保该商品不会停产;如果unitsInStock低于reorderLevel(并且unitsOnOrder为0),我们会显示错误消息。
后记
GraphQL 是管理 JavaScript 应用程序中数据的优秀工具。它与SpreadJS配合得很好,尤其是我们的数据绑定功能组件。本教程展示了 GraphQL 和 SpreadJS如何简单地构建应用程序。 GraphQL 和 SpreadJS都有更多功能可供探索,因此您可以做的事情远远超出了这个示例。
扩展链接: