文档章节

有关handsontable的一些简单操作

至尊小斌
 至尊小斌
发布于 2017/04/28 20:19
字数 2897
阅读 1174
收藏 3

 

官网地址:https://handsontable.com/

handsontable简介

       handsontable是一个类似Excel表格编辑器,支持丰富的展现和交互,有多样的单元格类型供配置。核心是由原生JavaScript构建。

       除了核心表格渲染(实质就是js操作table,计算元素位置,自定义绑定事件处理),大部分功能以插件提供。可以灵活构建插拔,自定义添加新功能插件。

1.常用属性

1.1 data:初始化组件表格数据,data可以有两种格式。

第一种是二维数组:

data: [
	['日期','销售地点','销售商品','单价','销量'],
	['2017-01', '北京', '冰箱', '3399', 530],
	['2017-01', '天津', '空调', '4299', 522],
	['2017-01', '上海', '洗衣机', '1299', 544],
	['2017-01', '广州', '彩电', '4599', 562],
	['2017-01', '深圳', '热水器', '1099', 430],
	['2017-02', '重庆', '笔记本电脑', '4999', 666],
	['2017-02', '厦门', '油烟机', '2899', 438],
	['2017-02', '青岛', '饮水机', '899', 620],
	['2017-02', '大连', '手机', '1999', 500]
];

第二种是对象数组:如果使用该方式渲染数据,则不能使用插入列方法:insert_col和remove_col

data: [
	{'date': '2017-01', 'place':'北京', 'goods':'冰箱', 'price':3399, '销量':530},
	{'date': '2017-01', 'place':'天津', 'goods':'空调', 'price':4299, '销量':522},
	{'date': '2017-01', 'place':'上海', 'goods':'洗衣机', 'price':1299, '销量':544},
	{'date': '2017-01', 'place':'广州', 'goods':'彩电', 'price':4599, '销量':562},
	{'date': '2017-01', 'place':'深圳', 'goods':'热水器', 'price':1099, '销量':430},
	{'date': '2017-02', 'place':'重庆', 'goods':'笔记本电脑', 'price':4999, '销量':666},
	{'date': '2017-02', 'place':'厦门', 'goods':'油烟机', 'price':2899, '销量':438},
	{'date': '2017-02', 'place':'青岛', 'goods':'饮水机', 'price':1099, '销量':620},
	{'date': '2017-02', 'place':'大连', 'goods':'手机', 'price':1999, '销量':500}
]

1.2 colHeaders:显示列头数据(false/true/数组),默认值false,设置true则按A、B、C...显示,还可以自定义数组作为列头

colHeaders: ['日期', '地点', '商品', '单价', '销量']

1.3 rowHeaders:显示行头数据(false/true/数组),默认值false,设置true则按顺序1、2、3...显示,跟colHeaders一样可使用自定义数组作为行头

rowHeaders: [1, 2, 3, 4, 5, 6]

1.4 stretchH:自适应列宽,默认值none,last 将最后一列拉伸到最大,all 将所有列均匀拉伸

1.5 colWidths:设置每一列的宽度,数据可为数字、数字数组,stretchH与colWidths一起使用时,将先适配colWidths,然后在适配stretchH进行列宽拉伸

colWidths: 200 // 所有列宽都为200像素
colWidths: [100, 200, 300, 200, 100]

1.6 className:容器单元格的class属性(htCenter,htLeft,htRight,htJustify,htTop,htMiddle,htBottom),默认值undefined,这些属性将作为容器单元格内容的对齐方式

1.7 cell:指定单元格的某些属性(数组),如下:

cell: [
    {row:0, col:0, className: 'htRight htMiddle', editor: false}, // 右对齐垂直居中,只读
    {row:1, col:1, className: 'htLeft'} // 左对齐
]

1.8 contextMenu:是否启用右键菜单(true:启用默认配置,false:禁用右键菜单,数组),默认undefined,或者可用数组自定义那些操作可用

context:Menu: ["row_above", "row_below", "col_left", "col_right", "remove_row", "remove_col", "---------", "undo", "redo", "Read Only", "alignment", "Merge Cells"]

1.9 mergeCells:合并单元格(true允许合并单元格,对象数组),默认值false禁止合并单元格,若使用对象数组,将会合并对象数组中提供的单元格

mergeCells: [
	{row:0, col:0, rowspan:5, colspan:1},
	{row:5, col:0, rowspan:4, colspan:1}
]

1.10 startRows:初始行数

1.11 startCols:初始列数

1.12 customBorders:自定义单元格边框,可以用range指定一个范围,或者直接使用row、col指定单元格位置,用top、right、bottom、left分别设置单元格上下左右边框的属性。

customBorders: [
	{
		range: {
			from: {row: 1, col:1},
			to: {row: 3, col:3}
		},
		top: {width: 2, color: '#25e825'},
		right: {width: 2, color: '#25e825'},
		bottom: {width: 2, color: '#25e825'},
		left: {width: 2, color: '#25e825'}
	},
	{
		row: 2,
		col: 2,
		top: {width: 2, color: '#7687c5'},
		right: {width: 2, color: '#7687c5'},
		bottom: {width: 2, color: '#7687c5'},
		left: {width: 2, color: '#7687c5'}
	}
]

2. 核心方法

        接下来将写一个简单的例子,并使用一些方法进行讲解,下面先附上基础代码

<!DOCTYPE html>
<html>
	<head>
		<title>handsontable demo</title>
		<meta charset="utf-8">
		<link rel="stylesheet" href="css/handsontable.full.css">
		<script src="js/jquery.js"></script>
		<script src="js/handsontable.full.js"></script>
	</head>
	<body>
		<div id="example"></div>

		<script>
			var data = [
				['2017-01', '北京', '冰箱', '3399', 530],
				['2017-01', '天津', '空调', '4299', 522],
				['2017-01', '上海', '洗衣机', '1299', 544],
				['2017-01', '广州', '彩电', '4599', 562],
				['2017-01', '深圳', '热水器', '1099', 430],
				['2017-02', '重庆', '笔记本电脑', '4999', 666],
				['2017-02', '厦门', '油烟机', '2899', 438],
				['2017-02', '青岛', '饮水机', '899', 620],
				['2017-02', '大连', '手机', '1999', 500]
			];

			var hot = new Handsontable(document.getElementById('example'),{
				data: data,
				colHeaders: ['日期', '地点', '商品', '单价', '销量'], // 使用自定义列头
				rowHeaders: true,
				editor: false, // 禁用所有单元格编辑
				colWidths: 150, // 设置所有列宽为150像素
                contextMenu: false, // 禁用右键菜单
				mergeCells: [
					{row:0, col:0, rowspan:5, colspan:1},
					{row:5, col:0, rowspan:4, colspan:1}
				],
	            cell: [
	                {row: 0, col: 0, className: "htCenter htMiddle"}, // 设置下标为0,0的单元格样式 水平居中、垂直居中
	                {row: 5, col: 0, className: "htCenter htMiddle"}
	            ]
			});
		</script>
	</body>
</html>

先附上页面

上面我们已经将右键菜单禁用掉,现在将使用js对容器插入行列,并初始化插入列的数据

2.1 alter(action, index, amount, source, keepEmptyRows):alter方法用于改变表格结构,即插入或删除行列数据。

action:可用改变表格结构操作insert_row、insert_col、remove_row、remove_col

index:行列索引值,从0开始,insert操作将插入到该索引值的前一行/列

amount(可选,默认1):将要插入/删除的行列数

source(可选):行或列对象

keepEmptyRows(可选):防止删除空行,true/false

2.2 setDataAtCell(row, col, value, source):设置某个单元格的数据。

row:行号索引

col:列号索引

value:将要设置的单元格数据

source(可选):字符串标识中描述这一变化将如何改变数组(用于onAfterChange或onBeforeChange回调)

也可使用数组参数,如下:

hot.setDataAtCell([
	[9, 0, 'a'], // row col value
	[9, 1, 'b']
]);

2.3 setDataAtRowProp(row, prop, value, source):设置某个单元格的数据,与setDataAtCell不同的是数据源格式,setDataAtCell是使用二维数组做数据源,setDataAtRowProp是以对象数组做数据源,两个的功能实际上是一样的。

结合altersetDataAtCell方法我们将在下面做一个简单的例子:

// 在索引9行之前插入2个空行
hot.alter('insert_row', 9, 2);
// 对2个空行进行填充数据
hot.setDataAtCell([
	[9, 0, '2017-03'],
	[9, 1, '武汉'],
	[9, 2, '路由器'],
	[9, 3, 149],
	[9, 4, 692],
	[10, 0, '2017-03'],
	[10, 1, '杭州'],
	[10, 2, '移动电源'],
	[10, 3, 99],
	[10, 4, 785]
]);
hot.alter('remove_row', 6); // 移除索引为6的行

由于我们刚开始设置了合并列,现在删除第6行后,后面几行数据将会追加上去,所以新添加的一行(日期列)会被合并掉

2.4 clear():清空表格数据

2.5 colToProp(col):返回与给定列索引相对应的属性名。如果数据源是二维数组,将返回列索引。

2.6 countCols():返回表格总列数。

      countRows():返回表格总行数。

2.7 countRenderedCols():统计并返回被渲染的列数

      countRenderedRows():统计并返回被渲染的行数

2.8 countVisibleCols():统计并返回可见的列数,当返回-1时,表格不可见

      countVisibleRows():统计并返回可见的行数,当返回-1时,表格不可见

2.9 deselectCell():取消当前选中的单元格

2.10 getCell(row, col, topmost):获取单元格td元素,topmost为true它将从top最多覆盖返回TD元素

2.11 getCellMeta(row, col):返回指定行和坐标的单元格属性对象

2.12 getCellRenderer(row, col):返回指定单元格的渲染函数

2.13 getColHeader(col):根据列索引获取列头名称

     getRowHeader(row):根据行索引获取行头名称

2.14 getData(r, c, r2, c2):返回某个范围内的数据

2.15 getDataAtCell(row, col):返回指定单元格的数据

2.16 getDataAtCol(col)/getDataAtProp(prop)返回某一列的数据

        getDataAtRow(row):返回某一行的数据

2.17 getValue():返回当前选择单元格的数据

2.18 loadData():动态加载本地数据,此方法将会覆盖原有的数据

2.19 render():重新渲染表格

2.20 setCellMeta(row, col, key, val):设置单元格属性

方法太多,这边就没有一一列举出来,更多详细的方法介绍可以到官网上去看,下面我们还是通过几个例子来说明吧。

3. 案例解析

        使用案例我们将结合一些事件操作,在这些事件触发时我们将对单元格做一些样式渲染。

3.1 选择完单元格后进行渲染

        首先我们要知道单元格选择完成后将触发事件afterSelectionEnd,所以我们要在这个事件完成之后干点小事。

我们先在这里加点样式,后面将通过改变单元格class属性进行样式渲染

.selected-td{
	background: #8ef98e;
}

在这里我们先给网格对象在单元格选择完之后添加一个触发事件,执行一个函数打印出参数列表

hot.addHook('afterSelectionEnd', function(){
	console.log(arguments);
})

由此可见,我们得到的参数有哪些,我们现在能用到的最主要就是前面四个索引值,然后对该事件进行修改如下:

hot.addHook('afterSelectionEnd', function(r, c, r2, c2){
	// 清除所有扩展的样式
	for(var i = 0; i < hot.countRows(); i++){
		for(var j = 0; j < hot.countCols(); j++){
			// 在这里只需移除扩展样式selected-td就行,保留表格原有样式
			var className = hot.getCellMeta(i, j).className;
			if(className && className.lastIndexOf('selected-td') > 0){
				var index = className.indexOf('selected-td');
				hot.setCellMeta(i, j, 'className', className.substring(0, index) + className.substring(index+1, className.length));
			}
		}
	}
	// 给选择范围的单元格添加样式
	for(var i = r; i <= r2; i++){
		for(var j = c; j <= c2; j++){
			hot.setCellMeta(i, j, 'className', hot.getCellMeta(i, j).className + ' selected-td');
		}
	}
	// 重新渲染网格
	hot.render();
})

        这种方法去渲染网格的话,它的样式不会被改变,之前在做一个项目的时候,用到了类似这样的东西,那时候还不知道可以给网格渲染样式,只会用jquery动态给表格里的某个单元格添加样式,但是这样做的话,样式并没有被加载到单元格的属性对象中,由于handsontable页面数据是实时加载的,所以当表格带有滚动条的时候,一旦滚动由外部添加的样式马上会被清除掉,在这里是有setCellMeta方法进行设置就不会出现那种问题了。通过方法hot.getCellMeta(r, c).className我们就可以直接看到某个单元格被渲染的class样式。

3.2 单击单元格事件

    跟3.1一样,我们要给表格对象添加操作事件,就得先找出事件触发点在哪,由此我们得到afterOnCellMouseDown 事件,在这个事件之后我们还是一样会做一些操作,这里如果不知道有什么参数,还是可以将arguments打印出来查看,在这就不重复说了。

      为了减少代码冗余,我们将上面清除扩展样式的代码包装一下,封装到hot对象里面

/**
 * 移除所有单元格的某个样式
 * @param  {[type]} classVal 要移除的样式值
 */
hot.removeClass = function(classVal){
	for(var i = 0; i < hot.countRows(); i++){
		for(var j = 0; j < hot.countCols(); j++){
			var className = hot.getCellMeta(i, j).className;
			if(className && className.lastIndexOf(classVal) > 0){
				var index = className.indexOf(classVal);
				hot.setCellMeta(i, j, 'className', className.substring(0, index) + className.substring(index+1, className.length));
			}
		}
	}
}

    所以我们这次就可以简化方法了,如下:

// 鼠标按下时触发
hot.addHook('afterOnCellMouseDown', function(event, coords){
	this.removeClass('clk-td');
	hot.setCellMeta(coords.row, coords.col, 'className', hot.getCellMeta(coords.row, coords.col).className + ' clk-td');
});

以上基本上都是很基础的操作,还有很多东西不常用也没有写出来,大家如果需要的可以进入官网查看。

本次分享就到这里了,如果有哪里不清楚的可以留言哦,第一次写博客,还得请各位朋友多多关照(^-^)

© 著作权归作者所有

共有 人打赏支持
至尊小斌
粉丝 1
博文 1
码字总数 2897
作品 0
福州
程序员
私信 提问
用过handsontable的朋友,怎么把handsontable加入到requireJs里面使用

https://www.oschina.net/p/handsontable 最近新的项目需要把handsontable整合进去,目前都使用requireJs,要怎么把handsontable加载进去...

至尊小斌
2017/01/05
422
1
怎么用jquery调用Handsontable的js里的方法

怎么用jquery调用Handsontable的js里的方法, 例如我在页面上有个撤销的按钮,点击按钮怎么调用Handsontable.full.js里相应的撤销方法。还有,有多个表格,我选中其中一个表格的单愿格,旁边...

lynn_gsh
2014/12/04
1K
4
6月份最受欢迎的 15 个新的 jQuery 插件

每个月我们都会将上个月最新的和最受欢迎一些 jQuery 插件推荐给大家,现在让我们来看看上个月的最新热门 jQuery 插件吧。 1. jQuery++ jQuery++ 在 jQuery 1.7.x 的基础上增加了一些 DOM 助...

oschina
2012/07/04
5.1K
5
js-xlsx + handsontable + echarts实现excel上传编辑然后显示成图表

js-xlsx + handsontable + echarts 实现在前端导入excel数据并生成echart报表 前言 最近都在做类似 ERP 的项目,所以呢,又碰到一个比较变态的需求(至少对我来说是),在前端导入 excel 文件, 然...

noahlam
09/12
0
0
handsontable如何将ajax请求回来的数据放到handsontable的下拉列表里?

各位好,我的handsontable中的数据是select下拉列表框,显示的值是approvalUserName中的内容,但是approvalUserName传到后台进行保存的话,必须要传每个approvalUserName对应的approvalUserC...

非著名魔兽解说
2016/08/28
1K
1

没有更多内容

加载失败,请刷新页面

加载更多

eslint rules 规则

'rules': { "comma-dangle": ["error", "never"], //是否允许对象中出现结尾逗号 "no-cond-assign": 2, //条件语句的条件中不允许出现赋值运算符 "no-console": 2, //不允许出现console语句 ...

agenyun
32分钟前
1
0
类型判断时instanceof和equals的不同用法

接口设计时为了避免序列化的麻烦,将接口定义为参数为map<String,String>类型的接口,但是现在调用时需要转换当前的实体Bean为Map,接口接收方再把Map转换为另一个Bean实体。过程中的需要对类...

wangtx
38分钟前
1
0
vue 组件间传值(个人精编)

1.父组件向子组件传值 1⃣️.子组件标签绑定需要传递的参数名2⃣️.子组件页面使用props 接收参数 2.子组件向父组件传值  1⃣️.子组件使用$emit来触发一个自定义事件,并传递一个参...

MrBoyce
49分钟前
1
0
(荷兰)彼得·冯·门施著:博物馆学研究的目的

博物馆学研究的目的 (荷)彼得·冯·门施 尽管诸多关于博物馆学认知目的的不同看法可以被归纳为数个主要群体,但没有一个群体可以被称为“学派”。一般来说,学派是由于博物馆学研究目的的不...

乔老哥
58分钟前
2
0
Vue slot的用法

之前看官方文档,由于自己理解的偏差,不知道slot是干嘛的,看到小标题,使用Slot分发内容,就以为 是要往下派发内容。然后就没有理解插槽的概念。其实说白了,使用slot就是先圈一块地,将来...

peakedness丶
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部