在 React 中构建智能数据表
智能表的功能要求以及一些开源替代方案
引言
表格是网页上呈现数据最简单的方式之一。纯 HTML 表格可以满足基本的数据展示需求,但试图从中挤出任何复杂的功能很快就会让你感到沮丧。
这时,您需要就应用程序的开发路径做出一些重要决定。您可以开始围绕老式的 HTML 表格编写增强功能——但这会面临失去项目焦点的风险——或者您可以查看现有专门用于解决您问题的产品。
当今市场提供了专门的智能表格控件,它们可以为您处理表格部分,并提供额外的功能,包括选择模式、排序和列重排。
许多公司使用数据表来展示复杂的报告、仪表板、财务数据、销售结果,甚至是交互式电子表格。高需求催生了专业供给,因此表格在 Web 组件库中得到了很好的体现。
在本文中,我们将讨论智能表格应具备的功能,评估一些开源替代方案,并演示如何使用 GrapeCity 针对 React JavaScript 库的解决方案创建卓越的 HTML 智能数据表。我们假设您具有一定的 Web 开发经验,最好还熟悉 React。
表格功能
人们对智能数据表有一些关键功能上的期望
-
数据功能
- 从各种来源加载数据,包括本地文件、数据库和 API
- 搜索、筛选和排序选项
- 通过分页加载和显示大型数据集
- 导入和导出数据功能
-
UI 功能
- 显示和隐藏列
- 内联编辑
- 响应式设计——内置支持多种设备
- 可调整列宽以适应列内长数据点(多行评论)
- 横向和纵向滚动支持
- 数据验证和可视化,例如迷你图
现代框架内置了一些这些功能的实现。但是,您需要自己编写更高级的功能。
开源框架
React 由 Facebook 创建和维护,是一个非常流行的开源 JavaScript 库。目前,它占据了 JavaScript 框架市场份额的约 60%。由于其在行业中的广泛应用,许多产品应运而生,为基于 React 构建的应用程序提供服务,这也就不足为奇了。
以下是一些专为 React 构建的流行开源智能数据表库
- React Virtualized
- Fixed Data Table 2 for React
- React Data Table Component
- React Table
- React Data Grid
这些开源项目各有优缺点。根据您寻找的功能,其中一些组件比其他组件更好。
使用 React Data Grid 创建 React 应用
让我们使用 React Data Grid 构建一个新的基于 Node 的 React 应用程序,它是一个开源组件,其外观和感觉非常接近我们试图演示的内容。
安装 Node.js。然后,使用命令行控制台,创建一个新的 Node React 应用
npx create-react-app my-app
cd my-app
npm start
安装 React Data Grid 包。打开 package.json 文件,在 dependencies 部分添加这些行
"babel-loader": "^8.1.0",
"react-data-grid": "5.0.1",
"react-data-grid-addons": "5.0.4",
"bootstrap": "^4.5.2"
在 browserslist 部分之后追加以下行
"devDependencies": {
"immutable": "^4.0.0-rc.12"
}
要安装 React Data Grid 包及其依赖项,请运行 npm install
命令行指令
npm install
在 src 文件夹下添加一个新的 data 文件夹,并创建一个名为 data.js 的新文件。用户将使用这些数据来填充我们的数据网格
export const recentSales = [
{
id: 1,
country: "Canada",
soldBy: "Bill",
client: "Cerberus Corp.",
description: "Prothean artifacts",
value: 6250,
itemCount: 50
},
{
id: 2,
country: "Canada",
soldBy: "Bill",
client: "Strickland Propane",
description: "Propane and propane accessories",
value: 2265,
itemCount: 20
},
{
id: 3,
country: "USA",
soldBy: "Ted",
client: "Dunder Mifflin",
description: "Assorted paper-making supplies",
value: 4700,
itemCount: 10
},
{
id: 4,
country: "USA",
soldBy: "Ted",
client: "Utopia Planitia Shipyards",
description: "Dilithium, duranium, assorted shipbuilding supplies",
value: 21750,
itemCount: 250
},
{
id: 5,
country: "USA",
soldBy: "Ted",
client: "Glengarry Estates",
description: "Desks, phones, coffee, steak knives, and one Cadillac",
value: 5000,
itemCount: 5
},
{
id: 6,
country: "Germany",
soldBy: "Angela",
client: "Wayne Enterprises",
description: "Suit armor and run-flat tires",
value: 35000,
itemCount: 25
},
{
id: 7,
country: "Germany",
soldBy: "Angela",
client: "Stark Industries",
description: "Armor and rocket fuel",
value: 25000,
itemCount: 10
},
{
id: 8,
country: "Germany",
soldBy: "Angela",
client: "Nakatomi Trading Corp.",
description: "Fire extinguishers and replacement windows",
value: 15000,
itemCount: 50
},
{
id: 9,
country: "UK",
soldBy: "Jill",
client: "Spaceley Sprockets",
description: "Anti-gravity propulsion units",
value: 25250,
itemCount: 50
},
{
id: 10,
country: "UK",
soldBy: "Jill",
client: "General Products",
description: "Ion engines",
value: 33200,
itemCount: 40
}
];
在 src 文件夹下添加一个新的 components 文件夹,并创建一个名为 OpenSourceTable-Demo.js 的新文件
/my-app
/src
/components
OpenSourceTable-Demo.js
打开 OpenSourceTable-Demo.js 文件并添加以下代码。(在这里,我们导入 ReactDataGrid
组件并声明将由数据网格用作列定义和组件数据源的 React 状态变量)
import 'bootstrap/dist/css/bootstrap.min.css';
import React, { useState } from 'react';
import ReactDOM from "react-dom";
import ReactDataGrid from "react-data-grid";
import { recentSales } from "../data/data";
export const OpenSourceTableDemo = () => {
const [columns, setColumns] = new useState([
{ key: "id", name: "Id" },
{ key: "country", name: "Country" },
{ key: "soldBy", name: "Sold by" },
{ key: "client", name: "Client" },
{ key: "description", name: "Description" },
{ key: "value", name: "Value" },
{ key: "itemCount", name: "Item Count" }
]);
const [sales, setSales] = new useState(recentSales);
}
修改 OpenSourceTableDemo
组件,使其返回包含 ReactDataGrid
组件的 HTML
return (
<div className="card main-panel">
<div className="card-header">
<h1>Open Source</h1>
</div>
<div className="card-body">
<h5>React Data Grid Demo</h5>
<p>
Building a Smart Data Table in React with React Data Grid
</p>
<div className="container-fluid">
<div className="row">
<ReactDataGrid
columns={columns}
rowGetter={i => sales[i]}
rowsCount={recentSales.length}
/>
</div>
</div>
</div>
</div>);
编辑 App.js 文件,并用下面的行替换其内容
import React from 'react';
import './App.css';
import { OpenSourceTableDemo } from './components/OpenSourceTable-Demo.js'
function App() {
return (
<OpenSourceTableDemo/>
);
}
export default App;
现在运行应用程序
npm start
应用程序运行后,您将看到 React Data Grid 显示销售数据
为了展示该组件的一些功能,让我们开始自定义我们的开源数据网格,以支持单元格值更新、行排序和列重排。
实现单元格值更新
打开 OpenSourceTable-Demo.js 文件,并在每个网格列定义中添加 editable: true 属性
{ key: "id", name: "Id", editable: true },
{ key: "country", name: "Country", editable: true },
{ key: "soldBy", name: "Sold by", editable: true },
{ key: "client", name: "Client", editable: true },
{ key: "description", name: "Description", editable: true },
{ key: "value", name: "Value", editable: true },
{ key: "itemCount", name: "Item Count", editable: true }
添加一个新的 onGridRowsUpdated
函数来处理单元格更新并更新底层数据源
const onGridRowsUpdated = ({ fromRow, toRow, updated }) => {
const s = sales.slice();
for (let i = fromRow; i <= toRow; i++) {
s[i] = { ...s[i], ...updated };
}
setSales(s);
};
修改 ReactDataGrid
组件以添加 enableCellSelect={true}
属性和 onGridRowsUpdated={onGridRowsUpdated}
事件处理程序
<ReactDataGrid
columns={columns}
rowGetter={i => sales[i]}
rowsCount={recentSales.length}
enableCellSelect={true}
onGridRowsUpdated={onGridRowsUpdated}
/>
这些更改使您的 React Data Grid 能够处理更新并将它们持久化到底层数据源中
实现行排序
打开 OpenSourceTable-Demo.js 文件,并在每个列定义中添加 sortable: true
属性以启用列可排序性
{ key: "id", name: "Id", editable: true, sortable: true },
{ key: "country", name: "Country", editable: true, sortable: true },
{ key: "soldBy", name: "Sold by", editable: true, sortable: true },
{ key: "client", name: "Client", editable: true, sortable: true },
{ key: "description", name: "Description", editable: true, sortable: true },
{ key: "value", name: "Value", editable: true, sortable: true },
{ key: "itemCount", name: "Item Count", editable: true, sortable: true }
实现新的 sortRows
函数
const sortRows = (initialRows, sortColumn, sortDirection) => rows => {
const comparer = (a, b) => {
if (sortDirection === "ASC") {
return a[sortColumn] > b[sortColumn] ? 1 : -1;
} else if (sortDirection === "DESC") {
return a[sortColumn] < b[sortColumn] ? 1 : -1;
}
};
return sortDirection === "NONE" ? initialRows : [...rows].sort(comparer);
};
修改 ReactDataGrid
组件以实现 onGridSort
事件处理程序并引用我们刚刚创建的函数
<ReactDataGrid
columns={columns}
rowGetter={i => sales[i]}
rowsCount={recentSales.length}
enableCellSelect={true}
onGridRowsUpdated={onGridRowsUpdated}
onGridSort={(sortColumn, sortDirection) =>
setSales(sortRows(sales, sortColumn, sortDirection))
}
/>
回到网页,注意现在列是可以排序的
实现列重排
打开 OpenSourceTable-Demo.js 文件,并在 imports
部分之后添加此声明
const {
DraggableHeader: { DraggableContainer }
} = require("react-data-grid-addons");
将 draggable: true
属性添加到每个列定义中以启用列重排
{ key: "id", name: "Id", editable: true, sortable: true, draggable: true },
{ key: "country", name: "Country", editable: true, sortable: true, draggable: true },
{ key: "soldBy", name: "Sold by", editable: true, sortable: true, draggable: true },
{ key: "client", name: "Client", editable: true, sortable: true, draggable: true },
{ key: "description", name: "Description", editable: true, sortable: true, draggable: true },
{ key: "value", name: "Value", editable: true, sortable: true, draggable: true },
{ key: "itemCount", name: "Item Count", editable: true, sortable: true, draggable: true }
添加 onHeaderDrop
函数来处理列拖放事件
const onHeaderDrop = (source, target) => {
var columnsCopy = columns.slice();
const columnSourceIndex = columns.findIndex(
i => i.key === source
);
const columnTargetIndex = columns.findIndex(
i => i.key === target
);
columnsCopy.splice(
columnTargetIndex,
0,
columnsCopy.splice(columnSourceIndex, 1)[0]
);
setColumns(columnsCopy.splice());
setColumns(columnsCopy);
};
将您现有的 ReactDataGrid
组件包装在一个新的 DraggableContainer
组件中
<DraggableContainer onHeaderDrop={onHeaderDrop}>
<ReactDataGrid
columns={columns}
rowGetter={i => sales[i]}
rowsCount={recentSales.length}
enableCellSelect={true}
onGridRowsUpdated={onGridRowsUpdated}
onGridSort={(sortColumn, sortDirection) =>
setSales(sortRows(sales, sortColumn, sortDirection))
}
/>
</DraggableContainer>
重新运行应用程序,尝试移动网格列
这看起来不错,但实现这些功能却费了很多力。现在您需要维护这些代码。
总结
您可以通过多种方式创建和使用基于 React 的智能数据表。有些方法需要比其他方法更多的手动工作,但直到您花费足够的时间尝试使用它们,您才能知道这一点。
有大量的免费开源表格库可以满足您的日常需求。我们在本文中已经看到如何实现其中一个。
历史
- 2021 年 6 月 11 日:初始版本