65.9K
CodeProject 正在变化。 阅读更多。
Home

JavaScript 网格插件

starIconstarIconstarIconstarIconstarIcon

5.00/5 (9投票s)

2014年4月27日

CPOL

5分钟阅读

viewsIcon

25093

轻量级且易于使用的 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 的详细文档以及各种示例,以了解此插件如何根据不同的网格设置需求进行自定义

结论

如果您决定使用此代码,请随时报告您可能遇到的任何错误或问题。

© . All rights reserved.