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

在 React 中构建智能数据表

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (2投票s)

2021年6月11日

CPOL

5分钟阅读

viewsIcon

5728

智能表的功能要求以及一些开源替代方案

引言

表格是网页上呈现数据最简单的方式之一。纯 HTML 表格可以满足基本的数据展示需求,但试图从中挤出任何复杂的功能很快就会让你感到沮丧。

这时,您需要就应用程序的开发路径做出一些重要决定。您可以开始围绕老式的 HTML 表格编写增强功能——但这会面临失去项目焦点的风险——或者您可以查看现有专门用于解决您问题的产品。

当今市场提供了专门的智能表格控件,它们可以为您处理表格部分,并提供额外的功能,包括选择模式、排序和列重排。

许多公司使用数据表来展示复杂的报告、仪表板、财务数据、销售结果,甚至是交互式电子表格。高需求催生了专业供给,因此表格在 Web 组件库中得到了很好的体现。

在本文中,我们将讨论智能表格应具备的功能,评估一些开源替代方案,并演示如何使用 GrapeCity 针对 React JavaScript 库的解决方案创建卓越的 HTML 智能数据表。我们假设您具有一定的 Web 开发经验,最好还熟悉 React。

表格功能

人们对智能数据表有一些关键功能上的期望

  • 数据功能

    • 从各种来源加载数据,包括本地文件、数据库和 API
    • 搜索、筛选和排序选项
    • 通过分页加载和显示大型数据集
    • 导入和导出数据功能
  • UI 功能

    • 显示和隐藏列
    • 内联编辑
    • 响应式设计——内置支持多种设备
    • 可调整列宽以适应列内长数据点(多行评论)
    • 横向和纵向滚动支持
    • 数据验证和可视化,例如迷你图

现代框架内置了一些这些功能的实现。但是,您需要自己编写更高级的功能。

开源框架

React 由 Facebook 创建和维护,是一个非常流行的开源 JavaScript 库。目前,它占据了 JavaScript 框架市场份额的约 60%。由于其在行业中的广泛应用,许多产品应运而生,为基于 React 构建的应用程序提供服务,这也就不足为奇了。

以下是一些专为 React 构建的流行开源智能数据表库

这些开源项目各有优缺点。根据您寻找的功能,其中一些组件比其他组件更好。

使用 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 日:初始版本
© . All rights reserved.