Bootstrap

handsontable使用文档及扩展

文章目录

handsontable使用文档

一、介绍

Handsontable 是一个类似 Excel 表格编辑器,支持丰富的展现和交互,以及多样的单元格展现和配置

二、快速上手

1. 环境准备

vue2 安装

npm i handsontable @handsontable/vue

vue3 安装

npm i handsontable @handsontable/vue3
2. vue3使用示例

引用

import { HotTable } from '@handsontable/vue3'
import Handsontable from 'handsontable'
import 'handsontable/dist/handsontable.full.css'
import { registerAllModules } from 'handsontable/registry'
registerAllModules()

结构

<hot-table ref="wrapper" :settings="hotSettings"></hot-table>

逻辑

export default defineComponent({
	components:{ HotTable },
  name:'Handsontable',
	setup() {
    const data = reactive({
        hotSettings:{
          autoColumnSize:true,
          data:[
            {
              sort:1,
              nameIndex:'名称1',
              dateIndex:'2024年01月01日',
              selectIndex:'是'
            }
          ],
          colWidths:140, // 默认单元格宽度
          rowHeights:28, // 默认单元格高度
          minRows:0, // 默认数据最小行数
          wordWrap:true, // 单元格文字是否换行展示
          width:'100%', // auto  or  100%
          height:'100%', // auto  or  100%
          className:'htMiddle, htCenter',
          columns:[
            {
              title:'序号',
              data:'sort',
              type:'numeric', // 数值列
              width:40,
              align:'center'
            },
            {
              title:'名称',
              data:'nameIndex',
              type:'text', // 字符列
              align:'center'
            },
            {
              title:'日期',
              data:'dateIndex',
              type:'date', // 日期列
              align:'center',
              dateFormat:'YYYY年MM月DD日', // 表内显示格式
              datePickerConfig:{
                i18n:{
                  previousMonth:'Previous Month',
                  nextMonth:'Next Month',
                  months:[
                    '一月',
                    '二月',
                    '三月',
                    '四月',
                    '五月',
                    '六月',
                    '七月',
                    '八月',
                    '九月',
                    '十月',
                    '十一月',
                    '十二月'
                  ],
                  weekdays:['日', '一', '二', '三', '四', '五', '六'],
                  weekdaysShort:['日', '一', '二', '三', '四', '五', '六']
                }
              }
            },
            {
              title:'是否选择',
              data:'selectIndex',
              type:'dropdown', // 下拉选择列
              align:'center',
              source:['是', '否']
            }
          ],
          readOnly:false,
          mergeCells:true,
          licenseKey:'non-commercial-and-evaluation'
        }
    })
		
		return {
			...toRefs(data)
		};
	},
});

三、基础配置

1. 固定行列位置
fixedRowsTop:行数 //固定顶部多少行不能垂直滚动

fixedColumnsLeft:列数 //固定左侧多少列不能水平滚动
2. 拖拽行头或列头改变行或列的大小
manualColumnResize:true/false//当值为true时,允许拖动,当为false时禁止拖动

manualRowResize:true/false//当值为true时,允许拖动,当为false时禁止拖动
3. 延伸列的宽度
stretchH:last/all/none    //last:延伸最后一列,all:延伸所有列,none默认不延伸。
4. 手动固定某一列
manualColumnFreeze:true/false  

//当值为true时,选中某 一列,右键菜单会出现freeze this column选项,该选项的作用是固定这一列不可水平滚动,并会将这一列移动到非固定列的前面。再次右键菜单会出现unfreeze this column,意思是取消该列的固定,并将其还原到初始位置。
5. 拖动行或列到某一行或列之后
manualColumnMove:true/false //当值为true时,列可拖拽移动到指定列

manualRowMove:true/false //当值为true时,行可拖拽至指定行

//当属性的值为true时,行头或列头可以被拖拽移动,移动后该行或列将会被移动到指定位置,原先该行或列的后面部分自动上移或后退。移动的时候鼠标需选中行线或列线才行。
6. 设置当前行或列的样式
currentRowClassName://当前行样式的名称

currentColClassName://当前列样式的名称
7. 行分组或列分组
groups:[{cols:[0,2]},{cols:[3,5]},{rows:[0,4]},{rows:[5,7]}]

//上面的例子介绍了4个分组,第0-2列为一组,第3-5列为第二组,第0-4行为一组,第5-7列为第二组。分组可在行头或列头看见,分组可被展开或隐藏。
8. 允许排序
columnSorting:true/false/对象 //当值为true时,表示启用排序插件

//当值为true时,排序插件的使用可通过点击列头文字实现。当值为false时表示禁用排序。当值为对象时,该对象包含两个属性:column:列数。sortOrder:true/false,升序或降序,true为升序排列。当用对象启动插件后可用如下方式禁用插件:

hot.updateSettings({
  columnSorting:false
});

//排序的使用也可已直接调用sort()方法实现。如下操作:
if(hot.sortingEnabled){
  hot.sort(行数,true/false); //true为升序,false为降序
}
9. 显示行头列头
colHeaders:true/fals/数组 //当值为true时显示列头,当值为数组时,列头为数组的值

rowHeaders:true/false/数组 //当值为true时显示行头,当值为数组时,行头为数组的值
10. 数据显示
data:[[第一行数据],[第二行数据],...[第n行数据]]//对象数组

//获取数据的方法:hot.getData()。
//加载数据的方法:hot.loadData(data)。
//当不需要显示某一列的时候可用如下格式设置:

columns:[
  {data:0},
  {data:2}
]

//这里就不显示第二列数据,只有第1、3列数据
11. 右键菜单展示
contextMenu:true/false/自定义数组 //当值为true时,启用右键菜单,为false时禁用
12. 自适应列大小
autoColumnSize:true/false //当值为true且列宽未设置时,自适应列大小
13. minCols:最小列数
minRows://最小行数

minSpareCols://最小列空间,不足则添加空列

maxCols://最大列数

maxRows://最大行数

minSpareRows://最小行空间,不足则添加空行
14. observeChanges:true/false,当值为true时,启用observeChanges插件
15. colWidths:[列宽1,列宽2,…],列宽值
16. 自定义边框设置,可以进行初始化配置,如下:
customBorders:[{range:{from:{row:行数,col:列数},to:{row:行数,col:列数},上下左右设置}]
也可以声明customBorder:true,表示允许自定义单元格边框。
17. 单元格合并可以进行初始化配置,如下:
mergeCells:[{row:起始行数, col:起始列数, rowspan:合并行数, colspan:合并列数 },...],

也可以先声明单元格允许合并,mergeCells:true,再利用合并方法操作。

四、通用方法

1. clear():清空数据
2. createCol(index,amount,createAutomatically):添加列
index:列索引,amount:添加的列总数,createAutomatically:为一个数字
3. removeCol(index,amount):删除列
4. createRow(index):添加行
5. removeRow(index,amount):删除行
6. get(row,prop):根据行号和属性索引获取单元格的值
7. getAll():获取所有的数据
8. getCopyable(row,prop):根据行号和属性索引获取单个单元格的值
9. getCopyableText(start,end):获取被选择位置的值
start:开始选择的位置对象,end:结束选择的位置对象
10. getRange(start,end,destination):根据坐标获取数据
start:开始选择的位置对象,end:结束选择的位置对象,destionation:目的地map索引
11. getText(start,end):获取目标位置的数据
12. set(row,prop,value,source):设置单个单元格的值
row:行索引,prop:列索引,value:新值,source:hook插件的提供者
13. spliceCol(col,index,amount):添加或移除列数据
col:列索引,index:开始改变的数组索引,amount:改变数据的个数
14. spliceRow(row,index,amount):添加或删除行数据
row:行索引,index:开始改变的数组索引,amount:改变数据的个数

五、核心方法

1. 为handsontable添加钩子触发事件(具体方法可见 六、事件汇总)
addHook(key,callback):key为钩子方法名
2. alter(action,index,amount,source,keepEmptyRows)添加行或列,删除行或列
action:有4个值insert_row,insert_col,remove_row,remove_col

index:行索引,当存在时在索引处插入或删除,不存在时在当前行后插入

amount:默认值为1

source:行或列对象

keepEmptyRows:true/false,当值为true时,空行不被删除。
3. clear():清空表格数据
4. colOffset():获取可见的第一列的索引值
5. colToProp(col):返回给定索引列的列名,col为列索引
6. countCols():统计表格的所有列总数,并返回
countRows():统计表格的总行数,并返回
7. countEmptyCols(ending):
当ending的值为true时,统计所有空列的总数,返回总数显示再最右侧
countEmptyRows(ending):
当ending的值为true时,统计所有空行总数,返回总数显示在最下方
8. countRenderedCols():统计并返回被渲染的列数
countRenderedRows():统计并返回被渲染的行数
9. countVisibleCols():统计并返回可见的列数,当返回-1时,表格不可见
countVisibleRows():统计并返回可见的行数,当返回-1时,表格不可见
10.deselectCell():取消当前被选中的单元格
11. destory():移除dom对象中的表格
12. destoryEditor(reverOriginal)
去除当前编辑器,并选中当前单元格,渲染上该效果。如果reverOriginal不是true则被编辑的数据将被保存,如果为true,则会恢复之前的数据,不保存新的数据到单元格。
13. getActiveEditor():返回一个活跃的编辑对象。
14. getCell(row.col,topmost):
根据行列索引,获取一个被渲染的单元格,如果该单元格未被渲染则返回null
其中,row,col分别为行索引和列索引,topmost为表示是否是最上层,其值为true/false
15. getCellEditor():获取单元格的编辑器
16. getCellMeta(row,col):根据行列索引获取单元格的属性对象
17. getCellRenderer(row,col):根据单元格的行列索引获取单元格的渲染函数
18. getCellValidator():获取单元格的校验器
19. getColHeader(col):根据列索引获取列头名称
getRowHeader(row):根据行索引获取行头名称
20. getColWidth(col):根据列索引获取列宽
getRowHeight(row):根据行索引获取行高
21. getCoords(elem):获取元素的坐标
22. getCopyableData(startRow,startCol,endRow,endCol):获取指定范围的单元格数据
23. getData(row1,col1,row2,col2):获取指定范围的单元格的数据
24. getDataAtCell(row,col):根据行列索引获取单元格的值
25. getDataAtCol(col):根据列索引获取一列的数据
getDataAtRow(row):根据行索引获取一行的数据
26. getDataAtProp(prop):根据对象属性名获取相应的列的数据,prop为属性名
27. getDataAtRowProp(row,prop):根据行索引返回指定属性名的值
28. getInstance():获取一个handsontable实例
29. getPlugin(pluginName):根据插件名称获取一个插件实例
30. getSelected():获取被选中的单元格的索引数组
数组包括:startRow,stratCol,endRow,endCol4个值。
31. getSelectedRange():获取被选中的单元格的坐标
32. getSettings():获取对象的配置信息
33. getSourceDataAtCol(col):根据列号获取data source中的该列数据
getSourceDataAtRow(row):根据行号获取data source中的该行数据
34. .getValue():获取所有被选中的单元格的值
35. hasColHeaders():返回是否存在列头
hasRowHeaders():返回是否存在行头
36. isEmptyCol(col):根据列索引判断该列是否为空
isEmptyRow(row):根据行索引判断该行是否为空
37. isListening():判断当前handsontable实例是否被监听
listen():监听body中的input框
unlisten():停止监听
38. loadData(data):加载本地数据
39. populateFormArray(start,input,end,source,method,direction,deltas):
使用二维数组填充单元格,其中:
start:开始位置
input:二维数组
end:结束位置
source:默认为populateFromArray
method:默认为overwrite
direction:left/right/top/bottom
deltas:其值为一个数组
populateFormArray(row,col,input,endRow,,endCol,source,method,direction,deltas)
40. propToCol(prop):返回给定属性名的列索引,prop为属性名
propToRow(prop):返回给定属性名的行索引,prop为属性名
41. removeCellMeta(row,col,key):根据行列索引移除指定的属性对象
42. removeHook(key,callback):移除钩子方法
43. render():渲染表格
44. rowOffset():获取第一个可见行的索引
45. setCellMeta(row,col,key,val):设置参数属性和值到指定行列的单元格
46. setCellMetaObject(row,col,prop):设置属性对象到指定的单元格
47. setDataAtCell(row,col,value,source):设置新值到一个单元格
48. setDataAtRowProp(row,prop,value,source):设置指定行的属性值为指定的值
49. updateSettings(setting,init):修改初始化的配置信息
50. validdateCells(callback):使用验证器验证所有单元格

六、事件汇总

1. afterChange (changes: Array, source: String):1个或多个单元格的值被改变后调用
changes:是一个2维数组包含row,prop,oldVal,newVal4个属性。

source:其值为一个字符串,值可以为:alter,empty,populateFromArray,loadData,autofill,paste
2. beforeChange (changes: Array, source: String):开始改变单元格前被调用
changes:是一个2维数组,包括[row,prop,oldVal,newVal]这4个公共属性列

source是被改变的资源的名称
3. afterCellMetaReset ():重置单元格后调用
4. afterColumnMove (oldIndex: Number, newIndex: Number):列顺序被移动后触发
5. afterRowMove (oldIndex: Number, newIndex: Number):行被移动后调用
6. afterRowResize (col: Number, size: Number):行高改变后调用
7. afterRemoveCol (index: Number, amount: Number):当一列或多列被移动后调用
其中,index为开始移动的列的索引,amount为移动的列的总数量
8. afterRemoveRow (index: Number, amount: Number):当一行或多行被移动后调用
其中,index为被移动的行的索引,amount为被移动的行的总数量
9. beforeRemoveCol (index: Number, amount: Number):一列或多列被移动前调用
10. beforeRemoveRow (index: Number, amount: Number):一行或多行被移动前被调用
11. afterColumnSort (column: Number, order: Boolean):列排序后调用
12. beforeColumnSort (column: Number, order: Boolean):列排序前被调用
order:值为true时为升序,false时为降序
13. afterCreateCol (index: Number, amount: Number):添加行后被调用
index:新列的索引

amount:新列的数目
14. afterCreateRow (index: Number, amount: Number):添加行后被调用
index:新行的索引

amount:新行的数目
15. afterGetCellMeta (row: Number, col: Number, cellProperties: Object):获取单元格的配置信息后被调用
16. beforeGetCellMeta (row: Number, col: Number, cellProperties: Object):获取单元格属性前被调用
17. afterSetCellMeta(row: Number, col: Number, key: String, value: *):单元格样式被改变后调用
其中,cellProperties是一个单元格的渲染对象,key是改变样式的方式,例如合并单元格(merge),水平对齐(align)等。
18. afterGetColHeader (col: Number, TH: DOM Node):获取列头信息后被调用,TH是行头节点
19. afterGetColWidth (col: Number, response: Object):获取列宽后被调用
20. afterColumnResize (col: Number, size: Number):列宽度被手动修改后调用
21. afterCopyLimit (selectedRowsCount: Number, selectedColsCount: Number,copyRowsLimit: Number, copyColsLimit: Number)
当 copyRowsLimit 或者 copyColumnsLimit实现时被调用
22. afterDestroy ():销毁Handsontable实例后被调用
23. afterInit ():Handsontable实例被初始化后调用
24. beforeInit ():Handsontable实例被初始化前调用
25. beforeInitWalkontable():Walkontable实例被初始化前调用
26. afterLoadData ():新的数据被加载到数据资源后被调用
27. afterOnCellCornerMouseDown (event):鼠标点击单元格边角后被调用
28. afterOnCellMouseDown (event: Object, coords: Object, TD: Object):点击单元格或行头/列头后被调用
注意:点击行头或列头后索引的坐标为负数。例如点击列头单元格(0,0),则调用后的坐标为(0,-1)。
29. afterOnCellMouseOver (event: Object, coords: Object, TD: Object):鼠标停悬在单元格或行头/列头后调用
注意:点击行头或列头后索引的坐标为负数。例如点击行头单元格(0,0),则调用后的坐标为(0,-1)。
30. afterRender (isForced: Boolean):渲染表格后被调用
isForced:当其值为true表示是通过改变配置或数据引起的渲染,当值为false时表示通过滚动或移动、选中引起的渲染
31. beforeRender (isForced: Boolean):渲染前被调用
32. afterRenderer (TD: Object, row: Number, col: Number, prop: String, value: String, cellProperties: Object):手动渲染后调用
33. beforeChangeRender ():渲染被改变前调用
34. afterDeselect ():当前单元格被取消选中时调用
35. afterSelection (r: Number, c: Number, r2: Number, c2: Number):当一个或多个单元格被选中后调用
其中,r:选中的单元格起始行,r2:选中单元格的终止行

     c:选中的单元格的起始列,c2:选中的单元格的终止列
36. afterSelectionByProp (r: Number, p: String, r2: Number, p2: String):通过属性名选中单元格后调用
37. afterSelectionEnd (r: Number, c: Number, r2: Number, c2: Number):选中单元格鼠标抬起后调用
38. afterSelectionEndByProp (r: Number, p: String, r2: Number, p2: String):通过属性选中单元格鼠标抬起后调用
39. afterUpdateSettings ():配置参数配修改后调用
40. afterValidate (isValid: Boolean, value: Mixed, row: Number, prop: String,source: String)
当有验证器的时候调用验证器时被调用,验证结果作为第一个参数。
41. beforeValidate (value: Mixed, row: Number, prop: String, source: String):验证器被调用前调用该事件
42. beforeAutofill (start: Object, end: Object, data: Array):开始自动填充前调动
start:是一个第一个填充的单元格对象,例如:{row:4,col:3}

end:是最后一个填充的单元格对象,例如:{row:7,col:5}

data:是一个2维数组
43. beforeKeyDown (event: Object):按键按下前被调用
44. beforeSet (var: Object):单个配置值被设置前调用
45. beforeSetRangeEnd(coords: Array):设置范围结束前被调用
coords:是范围坐标
46. modifyCol(col: Number):列被修改时调用
47. modifyRow( row: Number):行被修改时调用
48. modifyColWidth (width: Number, col: Number):列宽被修改时调用
49. modifyRowHeight (height: Number, row: Number):行高被修改时调用

七、功能拓展

1. 自定义渲染

hansontable的渲染定义方式有多种,常见的有 NumericRenderer、TextRenderer、CheckboxRenderer,但他们都是通过registerRenderer来渲染 的,registerRenderer是hansontable的渲染公用方法,其他的渲染都是在此基础上扩展的。

cells: function (row, col, prop) {
   var cellProperties = {}
   cellProperties.renderer = negativeValueRenderer
   return cellProperties
}

function negativeValueRenderer(instance, td, row, col, prop, value, cellProperties) {
    const hot = Handsontable
    td.className = 'td' + row + '_' + col
    function handler() {
      const ParentComponent = {
        render() {
        	return h('div', {}, value)) // 此处可写render函数
        }
      }
      createApp(ParentComponent).mount(`.td${row}_${col}`)
    }
    handler()
} 
2. 单元格操作
1)自动填充单元格数据
fillHandle:true/false   //当值为true时,允许拖动单元格右下角,将其值自动填充到选中的单元格
2)合并单元格

初始化配置:mergeCells:[{row:起始行数,cols:起始列数,rowspan:合并的行数,colspan:合并的列数},…]

或者初始化声明:mergeCells:true //表示允许单元格合并

但单元格合并的操作,需如下操作:

hot.updateSettings({
	mergeCells: [
    { row: 1, col: 1, rowspan: 2, colspan: 2 },
    { row: 3, col: 3, rowspan: 1, colspan: 2 }
  ]
})
3)拆分单元格

拆分需要更新mergeCells配置,且需要重置当前单元格信息

hot.updateSettings({
  mergeCells: []
})

let rowCount = hot.countRows()
let colCount = hot.countCols()
  for (let row = 0; row < rowCount; row++) {
    for (let col = 0; col < colCount; col++) {
    // 获取单元格的元数据
      if (selection[0].end.row === row && selection[0].end.col === col) {
        hot.setCellMeta(row, col, 'colspan', 1)
        hot.setCellMeta(row, col, 'rowspan', 1)
      }
  }
}
4)只读模式
列只读,设置列属性:readOnly:true
单元格只读:cellProperties.readOnly = true
5)设置单元格的编辑类型
columns:[{type:类型}]
主要的类型有:
text:字符串
numeric:数字类型
date:日期框
checkbox:单选框
password:密码框

下面几种类型的使用比较特殊
select:下拉编辑器
columns:[
      {editor:'select',
      selectOption:[选项1,选项2...]},
      .......
]

dropdown:下拉选择
columns:[
     {type:'dropdown',
     source:[选项1,选项2...]},
     ......
]

autocomplete:自动匹配模式
columns:[
     {type:'autocomplete',
     source:[选项1,选项2...],
     strict:true/false,//值为true,严格匹配
     allowInvalid:true/false//值为true时,允许输入值作为匹配内容,只能在strict为true时使用
     },
     ......
]

handsontable:表格模式
columns:[
     {type:'handsontable',
     handsontable:{...},
     ......
]

自定义模式
data=[{
           title:html标签,
           description:描述,
           comments:评论,
           cover:封面
       },
       ......
]

自定义边界
customBorders:[
      range:{
               form:{row:行数,col:列数},          //起始行列
               to:{row:行数,col:列数},              //终止行列
               top/bottom/right/left:{                     //上下右左边线
                   width:像数,
                   color:颜色
               }
      }
]
6)评论
comments:true/false    //当值为true时可以显示评论,右键菜单可添加删除评论。
当值为true时,可设置单元格的评论内容,格式为:
cell:[
  {
    row:行数,
    col:列数,
    comment:评论内容
  }
]
3. 表格自定义校验
columns:[
  {
    type:'handsontable',
    validator: function (value, callback) {
      if(value){ // 可自定义规则
        callback(true)
      }else{
        callback(false)
      }
    }
  },
  ......
]
  
  
hot.validateCells(valid => {
  if (valid) {
		// 校验通过
  } else {
		// 校验未通过
  }
})
;