easytable 键盘方向键切换单元格功能
EasyTable本身自带的快捷键是支持方向键切换单元格的
实现逻辑跟回车下一格类似,也是在表格初始化时绑定键盘输入事件监听 → 判断编辑状态 → 跳转单元格
↑ 方向键需求
- 如果当前行以上行都不是空行,则清空表格中所有的空行
- 如果当前行往上存在空行,则正常跳转
- 如果处于编辑模式下,往上也要跳转自动变成编辑模式
↓ 方向键需求
- 在内容行单元格触发,复制当前行数据并粘贴到下一行中
- 在表格最后一行触发,表格往下插入一行(若当前行是有内容,则复制当前行数据;否则插入空行)
- 编辑模式下切换,切换后要保持编辑模式
← → 方向键需求
在编辑模式下切换,切换后要保持编辑模式
具体实现
/**
* 键盘输入事件监听方法
* @param {Object} event 按键事件
*/
listenKeydown(event) {
const { keyCode } = event; // 通过keyCode判断敲击的键位
let prevCellSelectionData; // 上一次选中的单元格数据
switch (keyCode) {
... // 回车监听处理
case 39: // → 方向键
if (this.isEasyTableEditorModel) {
// 编辑模式下,向右边跳转下一格可以编辑的单元格
const { rowKey } = this.easyTableEditorRow;
let colItem = this.easyTableColumns.find(item => item.field === this.easyTableEditorColumn.field),
xCoord = this.easyTableColumns.indexOf(colItem);
xCoord++;
if (xCoord !== this.easyTableColumns.length) colItem = this.easyTableColumns[xCoord];
const { edit, field } = colItem;
if (edit) {
this.jumpToEasyTableEditor(rowKey, field);
} else {
this.$refs.easyTable.setCellSelection({ rowKey, colKey: field });
// 清空编辑状态
this.clearEasyTableModifyMode();
}
} else { // 非编辑模式,更新表格选择项既可
const { cellSelectionData: { currentCell } } = this.$refs['easyTable'];
this.easyTableCellSelectionData = Object.assign({}, currentCell);
// 清空编辑状态
this.clearEasyTableModifyMode();
}
break;
case 37: // ← 方向键
if (this.isEasyTableEditorModel) {
// 编辑模式下,向右边跳转下一格可以编辑的单元格
const { rowKey } = this.easyTableEditorRow;
let colItem = this.easyTableColumns.find(item => item.field === this.easyTableEditorColumn.field),
xCoord = this.easyTableColumns.indexOf(colItem);
xCoord--;
if (xCoord >= 0) colItem = this.easyTableColumns[xCoord];
const { edit, field } = colItem;
if (edit) {
this.jumpToEasyTableEditor(rowKey, field);
} else {
this.$refs.easyTable.setCellSelection({ rowKey, colKey: field });
// 清空编辑状态
this.clearEasyTableModifyMode();
}
} else { // 非编辑模式,更新表格选择项既可
const { cellSelectionData: { currentCell } } = this.$refs['easyTable'];
this.easyTableCellSelectionData = Object.assign({}, currentCell);
// 清空编辑状态
this.clearEasyTableModifyMode();
}
break;
case 38: // ↑ 方向键
if (this.isEasyTableEditorModel) {
// 编辑模式下,向下复制当前行
let { rowKey } = this.easyTableEditorRow,
{ field } = this.easyTableEditorColumn;
if (rowKey > 0) rowKey--;
const { itemLength, itemWidth, qty } = this.tableData[rowKey];
this.jumpToEasyTableEditor(rowKey, field);
// ↑ 方向键点击方案二: 当跳转行以上行均为非空行时,清空表格所有空行,但如果有空行,则正常跳转,不清空
let targetArr = this.tableData.slice(0, rowKey); // 目标行以上的行数据
// 当进入上一行后,且行不为空,则判断当前行以上是否均为非空行,是则清除,否则正常跳转
if (...) {
// 没有空行,执行清空
}
} else { // 非编辑模式,更新表格选择项既可
const { cellSelectionData: { currentCell } } = this.$refs['easyTable'];
this.easyTableCellSelectionData = Object.assign({}, currentCell);
// 清空编辑状态
this.clearEasyTableModifyMode();
}
prevCellSelectionData = this.$refs.easyTable.cellSelectionData.currentCell;
break;
case 40: // ↓ 方向键
// ↓ 方向键处理方案二: 触发后无论是否编辑模式,只要是最后一行内容,则直接复制并粘贴
const { cellSelectionData: { currentCell } } = this.$refs['easyTable'];
// 上一次选择的单元格行数据
let currentRowKey = this.isEasyTableEditorModel ? this.easyTableEditorRow.rowKey : this.easyTableCellSelectionData.rowKey,
currentColKey = this.isEasyTableEditorModel ? this.easyTableEditorColumn.field : this.easyTableCellSelectionData.colKey;
const prevRowData = this.tableData[currentRowKey]; // 上一次选择的行数据
currentRowKey++;
// 只要在最后一行触发↓按键,就复制当前行内容(宽高数量均默认为0)
if (currentRowKey === this.tableData.length) {
this.copyItem(Object.assign({}, prevRowData, {rowKey: currentRowKey, itemLength: 0, itemWidth: 0, qty: 0}), currentRowKey);
this.$nextTick(() => { // 复制完成后强制进入新行的编辑模式
this.jumpToEasyTableEditor(currentRowKey, currentColKey);
});
} else { // 不是最后一行,先判断下一行是否为空行
const { itemNo, itemName } = this.tableData[currentRowKey]; // 截取产品编码&产品名称
if (itemNo === '' && itemName === '') { // 空行-产品编码&产品名称均为0,编辑和选中模式的处理一致,都是将当前行复制替换掉空行
this.replaceOrderDetailsRowData(currentRowKey, prevRowData);
this.$nextTick(() => { // 替换后将焦点放在"新"行的宽度上
this.jumpToEasyTableEditor(currentRowKey, 'itemLength');
});
} else { // 不是空行,则按照之前2.1的需求走-判断编辑选择模式
if (this.isEasyTableEditorModel) {
this.$nextTick(() => { // 编辑模式下,按方案一的逻辑跳转到下一行并开启编辑模式
this.jumpToEasyTableEditor(currentRowKey, currentColKey);
});
} else { // 非编辑模式下,直接执行跳转选择
this.easyTableCellSelectionData = Object.assign({}, currentCell);
this.$refs.easyTable.setCellSelection(currentRowKey, currentColKey);
// 清空编辑状态
this.clearEasyTableModifyMode();
}
}
}
break;
}
},
/**
* 跳转可编辑单元格方法
* @param {Number} rowKey 行索引
* @param {String} colKey 列索引
*/
jumpToEasyTableEditor(rowKey, colKey) {
const { isNumber } = this.easyTableColumns.find(item => item.field === colKey),
rowData = this.tableData[rowKey][colKey];
// 单元格格式为数值,同时值为0,跳转同时将输入框的内容设为空
this.$nextTick(() => {
this.$refs.easyTable.stopEditingCell();
if (isNumber && Number(rowData) === 0) {
this.$refs.easyTable.startEditingCell({ rowKey, colKey, defaultValue: '' });
} else { // 单元格没有格式,正常跳转
this.$refs.easyTable.startEditingCell({ rowKey, colKey });
}
});
// 将表格视图跟着一起跳转过去
this.$refs.easyTable.scrollToRowKey({ rowKey });
this.$refs.easyTable.scrollToColKey({ colKey });
}