基于Canvas+React的高性能Table表格 您所在的位置:网站首页 灵笼灯塔建模教程视频 基于Canvas+React的高性能Table表格

基于Canvas+React的高性能Table表格

2024-06-01 05:39| 来源: 网络整理| 查看: 265

        本人之前擅长客户端GDI+,疫情期间偶然了解到Web前端的Canvas画布。突发奇想,遂一发不可收拾,于是就有了这么个产物--基于Canvas+React的高性能Table表格,可咸可甜。

        语言:JavaScript、TypeScript、ES6语法;

        框架:React;

        技术:Canvas画布;

        性能:以装载并渲染18列、N行为标准,压测有以下性能指标(附,测试硬盘状态不是太好,08年的老盘)。

1如需自适应列宽,30万行(30万,耗时24S)2若无需自适应列宽,可达百万级(30万,耗时5S)3自适应列宽模式,14500行,耗时1.5S4无自适应列宽,14500行,耗时忽略不计

        特色:高性能、渲染流畅、操控顺滑、高扩展性(自定义派生列、单元格)、装载灵活、ES6语法、全程面向对象(class)、样式全部属性化(颜色、字体、尺寸、高度……抛弃繁杂的CSS样式表,降低入手门槛、维护复杂度);

目前已经支持的功能:

1、序号列、颜色(矩形、圆形)、进度、复选框、复选框集、按钮集、金额线、普通单元格;

2、右键显示隐藏列;

3、拖拽列索引顺序;

4、拖拽列宽;

5、自适应列宽;

6、数据结构(列表结构、树结构);

7、自定义行、单元格背景色、前景色;

8、自定义选中行、单元格的背景色;

9、焦点行背景色;

10、展开、折叠父子行;

11、表格数据排序;

12、表格内数据查找、定位;

13、数据选择模式(单选、多选--Shift辅助、鼠标滑动拖拽);

14、快捷键:↑(向上选择单元格或行)、↓(向下选择单元格或行)、←(向左选择单元格)、→(向右选择单元格)、PageUp(上翻一个显示范围)、PageDown(下翻一个显示范围)、Home(定位首行)、End(定位末行)、Ctrl+C(复制选中内容)、Ctrl+F(表格内数据查找、定位);

15、表格数据打印(目前针对页边距,还有点小瑕疵,需要手工调整一次页边距。大数据打印,尚且存有性能缺陷);

16、表格数据导出(时间紧迫,目前仅支持Excel);

17、多表头(支持表头合并);

18、单元格合并;

19、表头数据筛选、过滤(类似Excel数据筛选);

20、表格内容动态编辑(目前仅支持文本内容编辑,后续补充支持下拉框、日期框、数字框……);

21、表内,行数据拖拽交换(同级交换、父子级交换);

22、表外,行数据拖拽交换(不同表格之间,拖拽移除、或插入、或交换);

23、自定义右键菜单;

24、行定位(定位可视范围外、未渲染区域的选中行,并主动更新滚动条,使目标行处于可视范围内);

25、丰富的事件行为,总有一款适合您。单元格单击事件、行单击事件、行选择改变事件、表格勾选事件(行、列、单元格)、表格失焦事件、右键上下文选项单击事件……;

列表结构:

树结构:

右键菜单:

显示、隐藏列:

 列头数据筛选:

 

案例一:绑定Column、Row、Cell对象

import React, { useEffect, useState } from 'react'; import ColumnCollection from '@/EniacComponents/Table/Collections/ColumnCollection'; import RowCollection from '@/EniacComponents/Table/Collections/RowCollection'; import TableCore, { IFieldData } from '@/EniacComponents/Table/TableCore'; import Table from '@/EniacComponents/Table/Index'; const PageTableBindColumns = () => { const [columns, setColumns] = useState(new ColumnCollection()); const [rows, setRows] = useState(new RowCollection()); const BuildColumns = () => { let loColumns = columns; if (!loColumns || loColumns.Count === 0) { let loFieldList: IFieldData[] = [ { Name: 'colSequenceColumn', Text: '', Type: 'SequenceColumn' }, { Name: 'colCheckBoxColumn', Text: '', Type: 'CheckBoxColumn' }, { Name: 'name', Text: '姓名', Type: 'Column' }, { Name: 'age', Text: '年龄', Type: 'Column' }, { Name: 'sex', Text: '性别', Type: 'Column' }, { Name: 'items', Text: '功能清单', Type: 'CheckBoxListColumn' }, { Name: 'address', Text: '地址', Type: 'Column' }, { Name: 'assets_b', Text: '资产-本币', Type: 'AmountColumn' }, { Name: 'assets_y', Text: '资产-原币', Type: 'AmountColumn' }, { Name: 'controls', Text: '操作列', Type: 'ButtonColumn' }, ]; loColumns = new ColumnCollection(); for (let liIndex = 0; liIndex < loFieldList.length; liIndex++) { let loCulumnData = loFieldList[liIndex]; let loColumn = TableCore.CreateColumn(loCulumnData); loColumns.Add(loColumn); } setColumns(loColumns); } return loColumns; }; const BuildRows = (poColumns: ColumnCollection) => { if (!rows || rows.length === 0) { let loDataList = [ { name: '辛弃疾', age: 37, items: '喝酒,true;文臣,true;武将,true', sex: '男', address: '南宋', assets_b: 56832.215, assets_y: 56832.215, controls: '新增;修改;复制;审核;反审核;删除', }, { name: '苏洵', age: 62, items: '喝酒,true;文臣,true;武将,false', sex: '男', address: '北宋', assets_b: 65912.32, assets_y: 65912.32, controls: '新增;修改;复制;审核;反审核;删除', }, { name: '苏轼', age: 46, items: '喝酒,true;文臣,true;武将,true', sex: '男', address: '北宋', assets_b: 92615.68, assets_y: 92615.68, controls: '新增;修改;复制;审核;反审核;删除', }, { name: '苏辙', age: 43, items: '喝酒,true;文臣,true;武将,true', sex: '男', address: '北宋', assets_b: 4689.36, assets_y: 4689.36, controls: '新增;修改;复制;审核;反审核;删除', }, { name: '欧阳修', age: 78, items: '喝酒,true;文臣,true;武将,false', sex: '男', address: '北宋', assets_b: 9956592.36, assets_y: 9956592.36, controls: '新增;修改;复制;审核;反审核;删除', }, { name: '王维', age: 66, items: '喝酒,true;文臣,true;武将,false', sex: '男', address: '大唐', assets_b: 6588.66, assets_y: 6588.66, controls: '新增;修改;复制;审核;反审核;删除', }, { name: '杜甫', age: 48, items: '喝酒,true;文臣,true;武将,false', sex: '男', address: '大唐', assets_b: 6523698.99, assets_y: 6523698.99, controls: '新增;修改;复制;审核;反审核;删除', }, { name: '李白', age: 63, items: '喝酒,true;文臣,true;武将,true', sex: '男', address: '大唐', assets_b: 98217365.922, assets_y: 98217365.922, controls: '新增;修改;复制;审核;反审核;删除', }, { name: '李清照', age: 53, items: '喝酒,true;文臣,true;武将,true', sex: '女', address: '大宋', assets_b: 16591.52, assets_y: 16591.52, controls: '新增;修改;复制;审核;反审核;删除', }, { name: '施耐庵', age: 56, items: '喝酒,true;文臣,true;武将,true', sex: '男', address: '大明', assets_b: 32336.12, assets_y: 32336.12, controls: '新增;修改;复制;审核;反审核;删除', }, { name: '曹雪芹', age: 36, items: '喝酒,true;文臣,true;武将,true', sex: '男', address: '大清', assets_b: 615292.77, assets_y: 615292.77, controls: '新增;修改;复制;审核;反审核;删除', }, { name: '罗贯中', age: 68, items: '喝酒,true;文臣,true;武将,true', sex: '男', address: '元末明初', assets_b: 6668214.53, assets_y: 6668214.53, controls: '新增;修改;复制;审核;反审核;删除', }, ]; let loRows = new RowCollection(); loDataList.forEach((loRowData: object) => { let loRow = TableCore.CreateRow(poColumns, loRowData); if (loRow) { loRows.Add(loRow); } }); setRows(loRows); } }; const BuildTableData = () => { let loColumns = BuildColumns(); BuildRows(loColumns); }; useEffect(() => { BuildTableData(); }, [columns, rows]); return ( { Columns: columns, Rows: rows }} > ); }; export default PageTableBindColumns;

案例二:绑定数据源、事件的使用

import React, { useEffect, useState } from 'react'; import Table from '@/EniacComponents/Table/Index'; import ToolStripView from '../Components/ToolStrip/ToolStripView'; import { IFieldData } from '@/EniacComponents/Table/TableCore'; const PageTableBindFields = () => { const [fieldList, setFieldList] = useState([] as IFieldData[]); const [dataList, setDataList] = useState([] as object[]); const BuildFieldList = () => { if (!fieldList || fieldList.length === 0) { let loFieldList: IFieldData[] = [ { Name: 'name', Text: '姓名', Type: 'Column' }, { Name: 'age', Text: '年龄', Type: 'Column' }, { Name: 'items', Text: '功能清单', Type: 'CheckBoxListColumn' }, { Name: 'sex', Text: '性别', Type: 'Column' }, { Name: 'address', Text: '地址', Type: 'Column' }, ]; setFieldList(loFieldList); } }; const BuildDataList = () => { if (!dataList || dataList.length === 0) { let loDataList: any[] = [ { name: '辛弃疾', age: 37, items: '新增;修改;复制;删除;', sex: '男', address: '南宋' }, { name: '苏洵', age: 62, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '苏轼', age: 46, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '苏辙', age: 43, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '欧阳修', age: 78, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '王维', age: 66, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '杜甫', age: 48, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '李白', age: 63, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '李清照', age: 53, items: '新增;修改;复制;删除;', sex: '女', address: '大宋' }, { name: '施耐庵', age: 56, items: '新增;修改;复制;删除;', sex: '男', address: '大明' }, { name: '曹雪芹', age: 36, items: '新增;修改;复制;删除;', sex: '男', address: '大清' }, { name: '罗贯中', age: 68, items: '新增;修改;复制;删除;', sex: '男', address: '元末明初' }, { name: '辛弃疾', age: 37, items: '新增;修改;复制;删除;', sex: '男', address: '南宋' }, { name: '苏洵', age: 62, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '苏轼', age: 46, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '苏辙', age: 43, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '欧阳修', age: 78, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '王维', age: 66, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '杜甫', age: 48, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '李白', age: 63, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '李清照', age: 53, items: '新增;修改;复制;删除;', sex: '女', address: '大宋' }, { name: '施耐庵', age: 56, items: '新增;修改;复制;删除;', sex: '男', address: '大明' }, { name: '曹雪芹', age: 36, items: '新增;修改;复制;删除;', sex: '男', address: '大清' }, { name: '罗贯中', age: 68, items: '新增;修改;复制;删除;', sex: '男', address: '元末明初' }, { name: '辛弃疾', age: 37, items: '新增;修改;复制;删除;', sex: '男', address: '南宋' }, { name: '苏洵', age: 62, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '苏轼', age: 46, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '苏辙', age: 43, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '欧阳修', age: 78, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '王维', age: 66, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '杜甫', age: 48, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '李白', age: 63, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '李清照', age: 53, items: '新增;修改;复制;删除;', sex: '女', address: '大宋' }, { name: '施耐庵', age: 56, items: '新增;修改;复制;删除;', sex: '男', address: '大明' }, { name: '曹雪芹', age: 36, items: '新增;修改;复制;删除;', sex: '男', address: '大清' }, { name: '罗贯中', age: 68, items: '新增;修改;复制;删除;', sex: '男', address: '元末明初' }, { name: '辛弃疾', age: 37, items: '新增;修改;复制;删除;', sex: '男', address: '南宋' }, { name: '苏洵', age: 62, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '苏轼', age: 46, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '苏辙', age: 43, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '欧阳修', age: 78, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '王维', age: 66, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '杜甫', age: 48, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '李白', age: 63, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '李清照', age: 53, items: '新增;修改;复制;删除;', sex: '女', address: '大宋' }, { name: '施耐庵', age: 56, items: '新增;修改;复制;删除;', sex: '男', address: '大明' }, { name: '曹雪芹', age: 36, items: '新增;修改;复制;删除;', sex: '男', address: '大清' }, { name: '罗贯中', age: 68, items: '新增;修改;复制;删除;', sex: '男', address: '元末明初' }, { name: '辛弃疾', age: 37, items: '新增;修改;复制;删除;', sex: '男', address: '南宋' }, { name: '苏洵', age: 62, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '苏轼', age: 46, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '苏辙', age: 43, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '欧阳修', age: 78, items: '新增;修改;复制;删除;', sex: '男', address: '北宋' }, { name: '王维', age: 66, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '杜甫', age: 48, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '李白', age: 63, items: '新增;修改;复制;删除;', sex: '男', address: '大唐' }, { name: '李清照', age: 53, items: '新增;修改;复制;删除;', sex: '女', address: '大宋' }, { name: '施耐庵', age: 56, items: '新增;修改;复制;删除;', sex: '男', address: '大明' }, { name: '曹雪芹', age: 36, items: '新增;修改;复制;删除;', sex: '男', address: '大清' }, { name: '罗贯中', age: 68, items: '新增;修改;复制;删除;', sex: '男', address: '元末明初' }, ]; setDataList(loDataList); } }; useEffect(() => { BuildFieldList(); BuildDataList(); }, [fieldList, dataList]); const table_CellClick = (e: any) => { console.log('table_CellClick', e.Cell.Text); }; const table_RowClick = (e: any) => { console.log('table_RowClick', e.Row); }; const table_SelectionChanged = (e: any) => { console.log('table_SelectionChanged', e.Row); }; const table_CheckStateChanged = (e: any) => { if (e.Cell) { console.log('勾选单元格', e.Cell); } else if (e.Row) { console.log('勾选行', e.Row); } else if (e.Column) { console.log('勾选列', e.Column); } }; const table_ContextItemClick = (e: any) => { console.log('table_ContextMenuItemClick', e.Item); }; const table_GotFocus = (e: any) => { console.log('table_GotFocus', '获得焦点'); }; const table_LostFocus = (e: any) => { console.log('table_LostFocus', '失去焦点'); }; return ( { width: '100%', height: 'calc(100% - 43px)' }}> { FieldList: fieldList, DataList: dataList }} Items={null} OnCellClick={table_CellClick} OnRowClick={table_RowClick} OnSelectionChanged={table_SelectionChanged} OnCheckStateChanged={table_CheckStateChanged} OnContextItemClick={table_ContextItemClick} OnGotFocus={table_GotFocus} OnLostFocus={table_LostFocus} > ); }; export default PageTableBindFields;

本人对GDI+、Canvas相当痴迷,并小有成就。欢迎咨询、洽谈,相互学习、互相进步。 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有