申明
.[基于 handsontable 二次封装源码]: https://github.com/hf0913/vue-handsontable-element
.[handsontable 官网]: https://handsontable.com/
简要步骤
- 原表格标签修改为:Handsontable
- 对于 columns,key 或者 data 属性名都可以用来存放后端字段名
- 对于 columns 中 type 属性,仅支持:autocomplete、checkbox、date、dropdown、handsontable、numeric、password、text、time,默认为 text,切记不要设置 type 类型为其他值
示例代码
<template>
<Handsontable
:selectBoxConfig="selectBoxConfig"
:columns="columns"
v-model="tableData"
@click="handsontableClick"
@change="handsontableChange"
@getCore="getCore"
@cellDblClick="cellDblClick"
@getSelectOpts="getSelectOpts"
@changeSort="changeSort"
:options="options"
:singleSelectConfig="singleSelectConfig"
ref="handsontableRef"
:showLastTotalText="showLastTotalText"
/>
</template>
<script>
export default {
data() {
return {
showLastTotalText: true,
selectArr: [
{
test: "maple1",
id: 1
}
],
tableData: [],
columns: [
{
title: "表头名",
key: "common",
_width: 200,
readOnly: true,
allowEmpty: false,
type: "checkbox",
subType: "selection",
editor: false,
validator: (value, callback) => {
callback(true);
},
className: "htLeft htMiddle",
filterable: true,
},
{
title: "普通复选框",
key: "checked",
type: "checkbox",
checkedTemplate: "1",
uncheckedTemplate: "0"
},
{
key: "checked",
type: "checkbox",
subType: "selection"
},
{
title: "普通文本",
key: "text",
maxLength: 8
},
{
title: "地址级联选择",
data: "address",
subType: "address",
exchange: false,
extraField: "maple_address",
valueType: "label",
asyncOpts: () => {
return new Promiss((resolve, reject) => {
resolve([]);
});
},
props: {}
},
{
title: "普通级联选择",
data: "cascader",
exchange: false,
subType: "cascader",
asyncOpts: () => {
return new Promiss((resolve, reject) => {
resolve([]);
});
},
options: [],
extraField: "maple_address",
valueType: "label",
props: {}
},
{
title: "时间日期组合",
key: "datePicker",
subType: "datePicker",
props: {
type: "datetime",
format: "yyyy-MM-dd HH:mm:ss",
valueFormat: "yyyy-MM-dd HH:mm:ss"
}
},
{
title: "数字",
data: "numeric",
type: "numeric",
subType: "posInt",
allowZero: true,
numericFormat: {
pattern: "0.00",
min: 0,
max: 1208,
minInclude: false,
maxInclude: false,
}
},
{
title: "日期",
data: "date",
type: "date",
dateFormat: "YYYY-MM-DD"
},
{
title: "时间",
data: "time",
type: "time",
timeFormat: "HH:mm",
correctFormat: true
},
{
title:
"下拉框(优化模式,options属性或者source属性,接受一个回调函数,返回数据字典集合)",
data: "select",
type: "autocomplete",
options: () => this.selectArr,
extraField: "maple_love",
valueType: "id",
labelName: "test",
valueName: "id",
subType: "optimize",
maxMatchLen: 8,
visibleRows: 4,
exchange: false,
mnemonicCode: ["shorthandCode"]
},
{
title: "下拉框(ajax远程搜索)",
data: "select-maple",
subType: "select",
options: [
{
unitId: 1,
unitName: "maple1",
test: "ok"
},
{
unitId: 2,
unitName: "mtt1",
test: "tt"
}
],
_width: 200,
mnemonicCode: ["test"],
extraField: "maple_select",
valueType: "unitId",
labelName: "unitName",
valueName: "unitId",
asyncOpts: () => {
return new Promiss((resolve, reject) => {
resolve([]);
});
},
ajaxConfig: {
url:
"http://47.110.56.139:8008/api/foundation/unit/component",
method: "post",
queryField: "param",
data: {
pageNum: 1,
pageSize: 10,
param: ""
},
header: {
Authorization: "eyJhbGciOiJIUzUxMiJ9"
},
result: "data"
},
props: {
remote: true,
placeholder: "输入即搜索"
}
},
{
title: "操作",
subType: "handle",
_width: 140,
options: [
{
name: "复制",
color: "#409eff"
},
{
name: "添加",
color: "#67c23a"
},
{
name: "删除",
color: "#f56c6c"
}
]
}
],
options: {
maxRows: 12080,
minRows: 8,
height: 400,
readOnly: false,
columnSorting: true,
wordWrap: false,
cacheId: "inventoryPricingMainTable",
openCache: false,
nestedHeaders: [
["A", { label: "B", colspan: 8 }, "C"],
[
"D",
{ label: "E", colspan: 4 },
{ label: "F", colspan: 4 },
"G"
],
[
"H",
{ label: "I", colspan: 2 },
{ label: "J", colspan: 2 },
{ label: "K", colspan: 2 },
{ label: "L", colspan: 2 },
"M"
],
["N", "O", "P", "Q", "R", "S", "T", "U", "V", "W"]
],
cells: (row, column, prop) => {
const cellProperties = {};
if (row === this.myValue.length - 1) {
cellProperties.readOnly = true;
cellProperties.comment = {
value: "备注内容",
readOnly: true
};
}
if (row === this.core.countRows() - 1) {
cellProperties.editor = false;
}
return cellProperties;
},
columnSummary: [
{
key: "n1",
type: "sum"
},
{
key: "n2",
type: "sum"
}
],
openEmptyValid: true,
hasDefaultValFileds: ["字段一", "字段二"],
openSort: true,
customSort: true,
allowFilters: true,
multiColumnSorting: true,
multiColumnSorting: {
initialConfig: [
{
column: 1,
sortOrder: "asc"
},
{
column: 0,
sortOrder: "desc"
}
]
},
customValidate: ({ isValid, value, row, key }) => {
return true;
},
customCellDblClick: ({ row, col, $el, core }) => {
return true;
},
takeoverCheckAll: o => {
}
},
core: Object,
selectBoxConfig: {
key: "checkbox",
col: 0
},
singleSelectConfig: {
key: "checked",
openAbled: false
strict: false
}
};
},
methods: {
getCore(v) {
this.core = v;
},
handsontableChange(o) {
const {
getKeyChange,
filterKeysChanges,
changes = [[]],
changeCurrentCell,
checked
} = o;
getKeyChange("你需要监听的字段名1", changes, true).map(
([row, key, oldVal, newVal]) => {
console.log(row, key, oldVal, newVal);
}
);
getKeyChange("你需要监听的字段名2", changes, true).map(
([row, key, oldVal, newVal]) => {
console.log(row, key, oldVal, newVal);
}
);
filterKeysChanges({
filterSummaryRow: true,
changes,
keys: ["你需要监听的字段名1", "你需要监听的字段名2"],
callback: ({
row,
key,
oldVal,
newVal,
changeCurrentCell,
index
}) => {
console.log(row, key, oldVal, newVal, index);
}
});
},
handsontableClick(o) {
console.log(o, "点击事件");
},
getData() {
this.$refs.handsontableRef
.getData((item, index) => {
item = {
...item,
notAddabled: false,
maple: index
};
return item;
})
.then(({ value, valid, columns }) => {
console.log(value, valid, columns);
});
},
cellDblClick({ coord, mouseEvent, $el }) {
console.log(coord, mouseEvent, $el);
},
getSelectOpts(o) {
console.log("getSelectOpts", o);
},
utils() {
return utils;
},
changeSort(o) {
this.$emit("changeSort", o);
},
clearSort(t) {
return this.$refs.mapleHandsontableRef.clearSort();
},
changeCheckAllabled(bl) {
return this.$refs.changeCheckAllabled(bl);
}
}
};
</script>
#### 使用说明 1. 关于下拉框,建议使用【title: "下拉框(优化模式,options 属性或者
source 属性,接受一个回调函数,返回数据字典集合)"】这种类型 2.
获取某一个单元格值:this.core.getDataAtCell(row,col) 3.
获取某一行数据:this.core.getDataAtRow(row) 4.
获取某一列数据:this.core.getDataAtCol(col) 5.
折叠行,https://handsontable.com/docs/7.4.2/demo-nested-rows.html 6.
设置某一个单元格的值:this.core.setDataAtCell(row, col, value,
'标记'),强烈不建议用在批量修改数据 7. 关于 core 获取,可以通过@getCore
方法,查看上面的示例代码,change 方法和 click 方法也会返回 core 对象 8. 请勿使用
setTimeout 来达到视图层更新 9. 修改数据,如果视图没有响应式渲染,请调用
this.core.updateSettings({data: this.tableData}); ##### 注意事项
全局修改该组件样式,会影响严重组件布局与功能,切记~