easytable 键盘方向键切换单元格功能

377 阅读3分钟

easytable 键盘方向键切换单元格功能

EasyTable本身自带的快捷键是支持方向键切换单元格的

实现逻辑跟回车下一格类似,也是在表格初始化时绑定键盘输入事件监听 → 判断编辑状态 → 跳转单元格

↑ 方向键需求

  1. 如果当前行以上行都不是空行,则清空表格中所有的空行
  2. 如果当前行往上存在空行,则正常跳转
  3. 如果处于编辑模式下,往上也要跳转自动变成编辑模式

↓ 方向键需求

  1. 在内容行单元格触发,复制当前行数据并粘贴到下一行中
  2. 在表格最后一行触发,表格往下插入一行(若当前行是有内容,则复制当前行数据;否则插入空行)
  3. 编辑模式下切换,切换后要保持编辑模式

← → 方向键需求

在编辑模式下切换,切换后要保持编辑模式


具体实现

/**
 * 键盘输入事件监听方法
 * @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 });
}