JavaScript 网格插件
轻量级且易于使用的 JavaScript 插件,用于创建 UI 网格
引言
在数据驱动的应用程序中,我们经常需要以网格(Grid)的形式显示信息。为此,我们通常可以使用一系列基于 JavaScript 和 jQuery 的可用插件。当我进行一项这样的需求时,我尝试使用了许多此类网格插件,但发现没有一个足够好,能够同时处理 JSON 数据、应用各种模板和自定义,并且保持轻量级。我需要动态更新数据、基于事件的行更新、将输入元素直接绑定到 JSON 数据源、处理复杂的模板等。
虽然像 AngularJS、Sencha 等框架可以帮助实现这些功能,但它们的体积庞大,仅仅为了创建一个网格就加载整个框架就显得“杀鸡用牛刀”了。所以我下定决心要解决这个特定的问题,并开始着手开发一个完全用 JavaScript 编写且不依赖 jQuery 等辅助库的插件。
这个插件的优点在于它轻量级(压缩后约 13KB)、不依赖辅助库,并且高度可定制。我创建它的初衷是考虑到创建 Web UI 网格时可能存在各种不同的需求,用户应该能够微观地管理整个网格模板。这个插件的名字叫做 GridJS,它提供了一种非常简单的方式来设置 UI 网格并将其与 JSON 数据绑定。
优点
JSON 数组驱动
这个插件以 JSON 数组格式的数据作为其数据源。它的好处是,只要数据是 JSON 格式,我们就可以灵活地将其分配给网格作为数据源。
模板化
我们可以在网格中使用模板(形式为 {{value}}
),这些模板可以是 JSON 数组数据源中的任何对象属性,可以是长串的对象和属性,甚至可以是自定义函数,用于为数据网格中的数据分配基于规则的值。
输入绑定
输入绑定非常简单。任何输入元素都可以直接绑定到 JSON 数组中的特定属性。当用户在输入字段中输入数据时,网格的数据源会相应更新。甚至可以单独获取数据更改。
独立 ID
每一行、每一列以及包含的输入元素(已分配 ID 的)都会有唯一的 ID,以便在网格渲染后进行后处理和引用。
分页
单个网格页面可以包含任意数量的行,其余的可以通过分页访问,分页可以在定义每页行数后随时激活。
事件处理程序
有网格加载、行添加、页面更改前、页面更改后等事件处理器。
顺序行颜色
可以为行设置任意数量的顺序颜色。当序列中的所有颜色都应用完毕后,颜色循环将从颜色列表的开头重新开始。这使得我们能够以最少的精力创建令人惊叹的网格。
应用自定义 CSS
几乎可以为网格内的任何元素应用自定义 CSS。您可以为整个网格、页眉、数据行、特定列设置自定义 CSS 类,如果这还不够,还可以为分页的普通数字和活动数字设置自定义 CSS。
数万条记录
有时,我们需要拥有包含数千条记录的非常大的网格。这个插件可以处理大量记录,甚至可以提供分页支持。
Using the Code
使用这个插件非常简单。首先,我们需要像其他表格一样为我们的网格创建一个 HTML 标记。然后,我们只需要应用模板来显示网格中的值。模板功能允许我们将模板直接替换为 JSON 数组数据源中的特定数据。
步骤 1
在 HTML 页面中包含 GridJS 脚本。
<head>
<script type="text/javascript" src="Scripts/grid.main.js"></script>
</head>
第二步
按如下方式创建您的网格标记
- 使用
<gridJS-grid>
自定义元素来创建网格。 - 在 <gridJS-grid> 中使用
<headerRow>
元素来创建页眉行。 - 在 <gridJS-grid> 中使用
<dataRow>
元素来创建数据行模板。 - 在 <gridJS-grid> 中使用
<footerRow>
元素来创建页脚行。 - 在
<headerRow>、
<dataRow>
和<footerRow>
中添加<column>
元素来向网格添加列。
<gridJS-grid>
自定义元素在插件加载时使用 document.registerElement()
进行了内部注册。但是,即使浏览器不支持 registerElement
,网格仍然会渲染,但自定义元素不会被浏览器识别。有关此内容的更多信息,请参阅此链接
例如
<gridjs-grid id="gridNorthWind" class="NorthWindGrid">
<headerRow class="NorthWindGridHeaderRow">
<column><b>Order ID</b></column>
<column><b>Customer ID</b></column>
<column><b>Emp ID</b></column>
<column><b>Order Date</b></column>
<column><b>Shipped Date</b></column>
<column><b>Freight</b></column>
<column><b>Ship Name</b></column>
<column><b>Ship City</b></column>
<column><b>Ship Postal Code</b></column>
<column><b>Ship Country</b></column>
</headerRow>
<dataRow class="NorthWindGridRow">
<column>{{OrderID}}</column>
<column>{{CustomerID}}</column>
<column>{{EmployeeID}}</column>
<column>{{GetOrderDate()}}</column>
<column>{{GetShippedDate()}}</column>
<column>{{Freight}}</column>
<column>{{ShipName}}</column>
<column>{{ShipCity}}</column>
<column>{{ShipPostalCode}}</column>
<column>{{ShipCountry}}</column>
</dataRow>
<footerRow>
</footerRow>
</gridjs-grid>
在此之后,唯一剩下的就是初始化一个新的 gridJS
对象,设置其属性和数据源,以启动我们的 UI 网格。
var gridJS = new GridJS({
gridId: 'gridNorthWind',
dataSource: NorthWindDataSource,
cellPadding: 6,
pagination: 10,
pageButtonCss: { normalCss: 'NorthWindPaginationButton', activeCss: '' },
dataRowColors: ["#0B6121", "#0A2A0A"]
})
.addCustomFunction("GetOrderDate", function (data, rowIndex) {
var date = new Date(Date.parse(data[rowIndex].OrderDate));
return getDate(date);
})
.addCustomFunction("GetShippedDate", function (data, rowIndex) {
var date = new Date(Date.parse(data[rowIndex].ShippedDate));
return getDate(date);
});
//returns meaningful date format
function getDate(rawDate) {
month = rawDate.getMonth(),
day = rawDate.getDate(),
year = rawDate.getYear();
return month + "/" + day + "/" + year;
}
JSON 数组形式的示例数据源
(function (w) {
var northWindDataSource =
{
"odata.metadata": "http://services.odata.org/V3/Northwind/Northwind.svc/$metadata#Orders"
, "value":
[
{
"Order_Details":
[
{ "OrderID": 10248, "ProductID": 11, "UnitPrice":
"14.0000", "Quantity": 12, "Discount": 0 }
, { "OrderID": 10248, "ProductID": 42, "UnitPrice":
"9.8000", "Quantity": 10, "Discount": 0 }
, { "OrderID": 10248, "ProductID": 72, "UnitPrice":
"34.8000", "Quantity": 5, "Discount": 0 }
]
, "OrderID": 10248
, "CustomerID": "VINET"
, "EmployeeID": 5
, "OrderDate": "1996-07-04T00:00:00"
, "RequiredDate": "1996-08-01T00:00:00"
, "ShippedDate": "1996-07-16T00:00:00"
, "ShipVia": 3
, "Freight": "32.3800"
, "ShipName": "Vins et alcools Chevalier"
, "ShipAddress": "59 rue de l'Abbaye"
, "ShipCity": "Reims"
, "ShipRegion": null
, "ShipPostalCode": "51100"
, "ShipCountry": "France"
}
,...{}};
w["NorthWindDataSource"] = northWindDataSource.value;
})(window);
步骤 3
调用我们 gridJS
对象的 draw()
函数来绘制网格。
gridJS().draw();
就这样,我们就得到了一个 UI 网格,其中包含了我们创建的所有数据绑定,而且毫不费力。
关注点
这个插件的代码会将自定义 <gridJS-grid>
元素内部的 HTML 转换为带有每行 ID 的 HTML 表格,以便稍后可以对其进行样式设置和引用。对于数据源中的每个 JSON 对象,都会添加一个新数据行,因此最终结果只是 <gridJS-grid>
元素内的 HTML 表格。不使用 jQuery 可以避免在基本场景和小型应用程序中完全包含 jQuery 代码。
浏览器支持
- Google Chrome: 很棒
- Firefox: 非常棒
- Internet Explorer: ???
示例和文档
您可以在以下链接找到 GridJS
API 的详细文档以及各种示例,以了解此插件如何根据不同的网格设置需求进行自定义
结论
如果您决定使用此代码,请随时报告您可能遇到的任何错误或问题。