🙏废话不多说系列,直接开整🙏
一、简介
Handsontable 是一个强大的 JavaScript 表格组件,允许用户创建和管理数据表格。下面是一个简单的使用实例,展示如何在网页中集成 Handsontable。
基本功能: 您可以将 Handsontable 用于所有类型的数据丰富、可访问的应用程序,使用户能够输入、编辑、验证和处理来自各种来源的数据,包括数据库和 API 等远程来源,以及 HTML 文档、Excel 文件、Google 表格和手动输入。
-
在线编辑表格对应的数据;
-
不仅支持原生的 JS ,还支持 多种不同的前端框架,如 Angular,React,Vue2, Vue3;
-
多列排序,过滤数据,导出文件,验证数据,条件格式,合并单元格,拖动单元格和指定列;
二、基本使用
(1)基本使用DEMO
示例步骤:① 引入 handsontable 的 CDN 加载对应的JS和CSS文件组件;② 定义一个二维数组作为基本的初始数据源;
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Handsontable 示例</title>
<script src="https://cdn.bootcdn.net/ajax/libs/handsontable/14.4.0/handsontable.full.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/handsontable/14.4.0/handsontable.full.css" rel="stylesheet">
<!--
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable/dist/handsontable.full.min.css">
<script src="https://cdn.jsdelivr.net/npm/handsontable/dist/handsontable.full.min.js"></script>
-->
<style>
#example {
width: 600px;
height: 300px;
overflow: hidden;
}
</style>
</head>
<body>
<div id="example"></div>
<script>
// 2. 初始化 Handsontable
const data = [
["", "Ford", "Tesla", "Toyota", "Honda"],
["2019", 10, 11, 12, 13],
["2020", 20, 11, 14, 32],
["2021", 30, 15, 12, 32]
];
const container = document.getElementById('example');
const hot = new Handsontable(container, {
data: data,
colHeaders: true,// 是否展示表头
rowHeaders: true,// 是否展示行号
filters: true,// 是否开启列数据过滤筛选功能
dropdownMenu: true,// 是否开启表头下拉功能(插入行,删除行等)
contextMenu: true,// 是否开启行数据操作功能菜单
licenseKey: 'non-commercial-and-evaluation' // 使用非商业和评估许可证
});
</script>
</body>
</html>
基本使用实例效果展示:
(2)配置相关
A. 开启表头和序号
const hot = new Handsontable(container, {
data: data,
colHeaders: true, // 开启表头
rowHeaders: true, // 开启序号
licenseKey: 'non-commercial-and-evaluation' // 使用非商业和评估许可证
});
- 未开启 表头 和 序号 展示
- 开启表头和序号
B. 开启列筛选功能
const hot = new Handsontable(container, {
data: data,// 表格二维数据(数组)
colHeaders: true,// 必要前提:开启表头
dropdownMenu: true,// 【核心】开启列下拉功能(支持向左/向右增加/删除/不显示列等只读操作)
licenseKey: 'non-commercial-and-evaluation' // 使用非商业和评估许可证
});
- 表头下拉功能菜单
C. 开启列数据筛选功能
const hot = new Handsontable(container, {
data: data,
colHeaders: true,// 必要前提1
// rowHeaders: true,
dropdownMenu: true, // 必要前提2
filters: true,// 【核心】开启过滤
licenseKey: 'non-commercial-and-evaluation' // 使用非商业和评估许可证
});
- 开启表格列数据筛选功能
D. 开启行数据操作功能
const hot = new Handsontable(container, {
data: data,
contextMenu: true, // 【核心】开启单元格数据右键菜单功能选项
licenseKey: 'non-commercial-and-evaluation' // 使用非商业和评估许可证
});
- 开启前无操作菜单
E. 导出配置
完整示例:官方示例教程 Export to CSV - JavaScript Data Grid | Handsontable
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Handsontable 示例</title>
<script src="https://cdn.bootcdn.net/ajax/libs/handsontable/14.4.0/handsontable.full.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/handsontable/14.4.0/handsontable.full.css" rel="stylesheet">
<style>
#example {
width: 600px;
height: 300px;
overflow: hidden;
}
</style>
</head>
<body>
<!-- 导入配置1.编写HTML问题 -->
<div class="example-controls-container">
<div class="controls">
<button id="export-file">Download CSV</button>
</div>
</div>
<div id="example"></div>
<script>
// 2. 初始化 Handsontable
const data = [
["", "Ford", "Tesla", "Toyota", "Honda"],
["2019", 10, 11, 12, 13],
["2020", 20, 11, 14, 32],
["2021", 30, 15, 12, 32]
];
const container = document.getElementById('example');
const hot = new Handsontable(container, {
data: data,
colHeaders: true,
rowHeaders: true,
dropdownMenu: true,
filters: true,
contextMenu: true,
licenseKey: 'non-commercial-and-evaluation' // 使用非商业和评估许可证
});
// 导入配置2:设置导入配置属性
const exportPlugin = hot.getPlugin('exportFile');
const button = document.querySelector('#export-file');
button.addEventListener('click', () => {
exportPlugin.downloadFile('csv', {
bom: false,
columnDelimiter: ',',
columnHeaders: false,
exportHiddenColumns: true,
exportHiddenRows: true,
fileExtension: 'csv',
filename: 'Handsontable-CSV-file_[YYYY]-[MM]-[DD]',
mimeType: 'text/csv',
rowDelimiter: '\r\n',
rowHeaders: true,
});
});
</script>
</body>
</html>
- 导出配置结果示例
F. 配置常见统计指标行
两个注意事项进行配置:① 元数据二维数组 额外加一行 [null] 用来统计占位;② 定义 handsontable 属性 columnSummary 进行配置;如下实例:
- 配置统计指标行
columnSummary 属性说明如下:
- sourceColumn:需要统计的列【0 表示第一列】;
- type:统计函数类型(有 sum, min , max, count, average)函数;
- destinationRow:显示于第N列,前提需要在元数据data数组上增加一个空数组元素 [null] 占位一行用来存放统计的数据;
- distinationColumn:显示在第几列,一般和 sourceColumn 保持一致即可。当然你可以指定显示在第几列即可。
- forceNumeric:是否提取数字进行统计。统计的时候只读取指定列的各个数据的数字进行统计。
官方示例地址传送门:Column summary - JavaScript Data Grid | Handsontable
G. 设置单元格注释说明
两个步骤实现:① 配置属性 comments:true;② 配置 指定单元格的定位和相关的注释说明;
const hot = new Handsontable(container, {
data: data,
colHeaders: true,
rowHeaders: true,
comments:true, // 1.开启注释
cell:[ // 2.定义指定单元格注释(此处 定义第一行第一列格子数据的说明为“Hello world!”)
{ row: 0, col: 0, comment: { value: 'Hello world!' } }
],
licenseKey: 'non-commercial-and-evaluation' // 使用非商业和评估许可证
});
展示结果示例:
- 配置指定单元格备注
H. 配置指定行显示数据格式和定义表头
① 定义表头列名;② 按照列顺序配置每一列元素的格式显示(非常常见的一类);
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Handsontable 示例</title>
<script src="https://cdn.bootcdn.net/ajax/libs/handsontable/14.4.0/handsontable.full.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/handsontable/14.4.0/handsontable.full.css" rel="stylesheet">
<!--
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable/dist/handsontable.full.min.css">
<script src="https://cdn.jsdelivr.net/npm/handsontable/dist/handsontable.full.min.js"></script>
-->
<style>
#example {
width: 600px;
height: 300px;
overflow: hidden;
}
</style>
</head>
<body>
<!-- 导入配置1.编写HTML问题 -->
<div class="example-controls-container">
<div class="controls">
<button id="export-file">Download CSV</button>
</div>
</div>
<div id="example"></div>
<script>
// 2. 初始化 Handsontable
const data = [
['Mercedes', 'A 160', '01/14/2021', 6999.95],
['Citroen', 'C4 Coupe', '12/01/2022', 8330],
['Audi', 'A4 Avant', '11/19/2023', 33900],
['Opel', 'Astra', '02/02/2021', 7000],
['BMW', '320i Coupe', '07/24/2022', 30500],
];
const container = document.getElementById('example');
const hot = new Handsontable(container, {
licenseKey: 'non-commercial-and-evaluation',
data: [
['Mercedes', 'A 160', '01/14/2021', 6999.95],
['Citroen', 'C4 Coupe', '12/01/2022', 8330],
['Audi', 'A4 Avant', '11/19/2023', 33900],
['Opel', 'Astra', '02/02/2021', 7000],
['BMW', '320i Coupe', '07/24/2022', 30500],
],
colHeaders: ['Car', 'Model', 'Registration date', 'Price'],
height: 'auto',
columns: [{
type: 'text',
},
{
// 2nd cell is simple text, no special options here
},
{
type: 'date',
dateFormat: 'MM/DD/YYYY',
correctFormat: true,
defaultDate: '01/01/1900',
// datePicker additional options
// (see https://github.com/dbushell/Pikaday#configuration)
datePickerConfig: {
// First day of the week (0: Sunday, 1: Monday, etc)
firstDay: 0,
showWeekNumber: true,
disableDayFn(date) {
// Disable Sunday and Saturday
return date.getDay() === 0 || date.getDay() === 6;
},
},
},
{
type: 'numeric',
numericFormat: {
pattern: '$ 0,0.00',
},
},
],
autoWrapRow: true,
autoWrapCol: true,
});
// 导入配置2:设置导入配置属性
const exportPlugin = hot.getPlugin('exportFile');
const button = document.querySelector('#export-file');
button.addEventListener('click', () => {
exportPlugin.downloadFile('csv', {
bom: false,
columnDelimiter: ',',
columnHeaders: false,
exportHiddenColumns: true,
exportHiddenRows: true,
fileExtension: 'csv',
filename: 'Handsontable-CSV-file_[YYYY]-[MM]-[DD]',
mimeType: 'text/csv',
rowDelimiter: '\r\n',
rowHeaders: true,
});
});
</script>
</body>
</html>
- 演示结果展示(表格数据格式化动态演示)
I. 配置列表默认只读和可排序
const hot = new Handsontable(container, {
data: data,
colHeaders: ["年份", "地点1", "地点2", "地点3", "地点4"],
rowHeaders: true,
columnSorting: true, // 开启排序
readOnly: true,
licenseKey: 'non-commercial-and-evaluation' // 使用非商业和评估许可证
});
效果展示:
(3)自定义相关
A. 配置表格样式:初始宽度、可拖拉宽度
官方示例地址:Date cell type - JavaScript Data Grid | Handsontable
const hot = new Handsontable(container, {
data: [
[ 'A1', 'B1', 'C1', ],
[ 'A2', 'B2', 'C2', ],
[ 'A3', 'B3', 'C3', ],
[ 'A4', 'B4', 'C4', ],
[ 'A5', 'B5', 'C5', ],
],
width: '100%',
height: 'auto',
colHeaders: true,
rowHeaders: true,
colWidths: 100, // 定义初始宽度
manualColumnResize: true, // 可拖拉改变宽度
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
展示结果:
B. 自定义表格颜色
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Handsontable 示例</title>
<script src="https://cdn.bootcdn.net/ajax/libs/handsontable/14.4.0/handsontable.full.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/handsontable/14.4.0/handsontable.full.css" rel="stylesheet">
<!--
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable/dist/handsontable.full.min.css">
<script src="https://cdn.jsdelivr.net/npm/handsontable/dist/handsontable.full.min.js"></script>
-->
<style>
#example {
width: 600px;
height: 300px;
overflow: hidden;
}
</style>
</head>
<body>
<!-- 导入配置1.编写HTML问题 -->
<div class="example-controls-container">
<div class="controls">
<button id="export-file">Download CSV</button>
</div>
</div>
<div id="example"></div>
<script>
// 2. 初始化 Handsontable
const data = [
{ id: 1, name: 'Ted', isActive: true, color: 'orange', date: '2015-01-01' },
{ id: 2, name: 'John', isActive: false, color: 'black', date: null },
{ id: 3, name: 'Al', isActive: true, color: 'red', date: null },
{ id: 4, name: 'Ben', isActive: false, color: 'blue', date: null },
];
const colors = ['yellow', 'red', 'orange', 'green', 'blue', 'gray', 'black', 'white',];
const yellowRenderer = (instance, td, ...rest) => {
Handsontable.renderers.TextRenderer(instance, td, ...rest);
td.style.backgroundColor = 'yellow';
};
const greenRenderer = (instance, td, ...rest) => {
Handsontable.renderers.TextRenderer(instance, td, ...rest);
td.style.backgroundColor = 'green';
};
const container = document.getElementById('example');
const hot = new Handsontable(container, {
data: data,
colHeaders: true,//["id", "name1", "isActive", "color", "date"],
rowHeaders: true,
columns: [
{ data: 'id', type: 'text' },
// 'text' is default, you don't actually need to declare it
{ data: 'name', renderer: yellowRenderer },
// use default 'text' cell type but overwrite its renderer with yellowRenderer
{ data: 'isActive', type: 'checkbox' },
{ data: 'date', type: 'date', dateFormat: 'YYYY-MM-DD HH:mm:ss' },
{ data: 'color', type: 'autocomplete', source: colors },
],
cell: [{ row: 1, col: 0, renderer: greenRenderer }],
cells(row, col) {
if (row === 0 && col === 0) {
this.renderer = greenRenderer;
return { renderer: this.renderer };
}
return {};
},
autoWrapRow: true,
autoWrapCol: true,
height: 'auto',
licenseKey: 'non-commercial-and-evaluation' // 使用非商业和评估许可证
});
// 导入配置2:设置导入配置属性
const exportPlugin = hot.getPlugin('exportFile');
const button = document.querySelector('#export-file');
button.addEventListener('click', () => {
exportPlugin.downloadFile('csv', {
bom: false,
columnDelimiter: ',',
columnHeaders: false,
exportHiddenColumns: true,
exportHiddenRows: true,
fileExtension: 'csv',
filename: 'Handsontable-CSV-file_[YYYY]-[MM]-[DD]',
mimeType: 'text/csv',
rowDelimiter: '\r\n',
rowHeaders: true,
});
});
</script>
</body>
</html>
展示样式:
- 设置指定颜色
此时点击导出的样式如下:(① 复选框选中与否:true/false; ② 颜色导出失效需要自己设置;)
(4)事件监听跟踪 Hook
- 官方示例地址:Events and hooks - JavaScript Data Grid | Handsontable
- 所有的事件跟进地址HOOK:Hooks API reference - JavaScript Data Grid | Handsontable
- 事件监听的用法模板:① 了解并记住相关的 hook事件名(见上述地址);② 套用调用 hook 事件模板方法(如下);
hot.addHook('方法名', (dataInfo, operteType) => {
console.log(`操作类型:${operteType} ,方法监听的数据 ${dataInfo}`);
});
// 注意:不同的方法名传入的 dataInfo 是不同的,所以这个方法传入的参数值也不近相同,请关注具体的 hook 对应的事件方法函数。
A. 新增/删除行-触发事件
// 事件1:hook 创建行之后
hot.addHook('afterCreateRow', (row, amount) => {
console.log(`${amount} row(s) were created, starting at index ${row}`);
});
// 事件3:hook 删除行之后
hot.addHook('afterRemoveRow', (row, amount) => {
console.log(`${amount} row(s) were removed, starting at index ${row}`);
});
B. 新增/删除列-触发事件
// 事件2:hook 创建列之后
hot.addHook('afterCreateCol', (col, amount) => {
console.log(`${amount} col(s) were created, starting at index ${col}`);
});
// 事件4:hook 删除列之后
hot.addHook('afterRemoveCol', (col, amount) => {
console.log(`${amount} col(s) were removed, starting at index ${col}`);
});
C.指定单元格数据变更后触发事件(含A和B操作)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.bootcdn.net/ajax/libs/handsontable/14.4.0/handsontable.full.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/handsontable/14.4.0/handsontable.full.css" rel="stylesheet">
<!--
教程:https://handsontable.com/docs/javascript-data-grid/events-and-hooks/
-->
</head>
<body>
<div id="example"></div>
<script type="text/javascript">
const container = document.getElementById('example');
const hot = new Handsontable(container, {
data: [
['Tesla', 2017, 'black', 'black'],
['Nissan', 2018, 'blue', 'blue'],
['Chrysler', 2019, 'yellow', 'black'],
['Volvo', 2020, 'yellow', 'gray']
],
colHeaders: true,// 开启表头
rowHeaders: true,// 开启序号
contextMenu: true,// 开启内容编辑
height: 'auto',
minSpareRows: 1, // 始终保持一空行
beforeChange(changes) {
lastChange = changes;
},
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
// 事件1:hook 创建行之后
hot.addHook('afterCreateRow', (row, amount) => {
console.log(`${amount} row(s) were created, starting at index ${row}`);
});
// 事件2:hook 创建列之后
hot.addHook('afterCreateCol', (col, amount) => {
console.log(`${amount} col(s) were created, starting at index ${row}`);
});
// 事件3:hook 删除行之后
hot.addHook('afterRemoveRow', (row, amount) => {
console.log(`${amount} row(s) were removed, starting at index ${row}`);
});
// 事件4:hook 删除列之后
hot.addHook('afterRemoveCol', (col, amount) => {
console.log(`${amount} col(s) were removed, starting at index ${row}`);
});
// 事件5:hook 数据改变后
hot.addHook('afterChange', (allInfo, operateType) => {
var arrInfo = (allInfo).toString().split(",");
var rowIndex = arrInfo[0], colIndex = arrInfo[1];
var changePreValue = arrInfo[2], changedValue = arrInfo[3];
console.log(`${allInfo} were changed!改变后的值为:${operateType}`);
console.log("坐标:", rowIndex, colIndex, "值:",changePreValue, changedValue)
});
</script>
</body>
</html>
测试演示:
- 演示数据改变后监听事件
hook
附录
- 官网地址:Handsontable 是一个 JavaScript 数据网格,外观和感觉都像一个电子表格 - 适用于 React、Angular 和 Vue
HandsonTable文档地址:handsontable.com/docs/javasc…HandsonTable开源地址:GitHub - handsontable/handsontable: JavaScript data grid with a spreadsheet look & feel. Works with React, Angular, and Vue. Supported by the Handsontable team ⚡
(1)注意事项:商用需购买许可证
- ⚠️
HandsonTable官方注意事项:
🙏至此,非常感谢阅读🙏