vxe表格实现键盘上下左右方向键移动聚焦

文章介绍了如何在VXE表格中使用键盘的上下左右方向键实现单元格的焦点移动。通过监听`@cell-click`和`@keyup`事件,获取当前选中单元格的行列号,并在按下方向键时更新焦点。代码示例提供了处理不同方向键的逻辑,包括处理边缘情况和寻找具有输入框的单元格进行焦点转移。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vxe表格分为vxe-table一般表格和vxe-grid高级表格,两者之间的区别我就不说啦,我们来实现这两种表格用键盘按动上下左右方向键达到移动聚焦的效果。话不多说,上正文!!!

首先在标签放入这两个事件:

  <vxe-grid @cell-click="cellClickEvent" @keyup="keyDown($event)"></vxe-grid>

主要是利用vxe表格内置的@cell-click事件,来监听点击单元格的行号和列号,相当于坐标轴的x轴和y轴。然后再利用@keyup键盘监听函数来监听方向键。思路有了,来肝!!!

 大家可以根据这DOM图来参考代码--------------------------------------------------------------------------------

let currCell = {} // 初始化当前选中的单元格行列号
let _currCell = {} // 拷贝初始化当前选中的单元格行列号

// 单元格点击事件
function cellClickEvent ({ row, column }) {
  const currRow = Number(row._X_ROW_KEY.split('_')[1])  // 当前行号
  const currCol = Number(column.id.split('_')[1]) // 当前列号
  currCell = { 'row': currRow, 'column': currCol }  // 当前行列号
}

// 方向键事件
function keyDown (e) {
  if (!(e.keyCode === 37 || e.keyCode === 38 || e.keyCode === 39 || e.keyCode === 40 || e.keyCode === 9)) return
// 如果不是上下左右方向键或Tab键直接返回(Tab键不放进来的话,会出现点击Tab键,聚焦到右边,但行列号还是原来位置)
  _currCell = JSON.parse(JSON.stringify(currCell)) // 深拷贝初始值
  const trs = document.querySelectorAll('.vxe-body--row') //所有的tr行
  const cols = trs[0].querySelectorAll('td') // 所有的td列(每一行的列号都一致)
  const maxTd = cols[cols.length - 1].getAttribute('colid').split('_')[1] // 最大列号
  const minTd = cols[0].getAttribute('colid').split('_')[1] //最小列号
  const maxTr = trs[trs.length - 1].getAttribute('rowid').split('_')[1] // 最大行号
  const minTr = trs[0].getAttribute('rowid').split('_')[1] // 最小行号

  // 方向左键 37
  if (e.keyCode === 37) {
    if (currCell.column <= minTd) return  // 如果当前单元格行号小于或等于最小列号,则直接返回
    for (let index = 0; index < 520; index++) { // 防止中间列出现缺失情况,行亦如此
      currCell.column--
      let targetCell = document.querySelector(`tr[rowid=row_${currCell.row}]`).querySelector(`.col_${currCell.column}`)
      if (targetCell) {
        if (targetCell.querySelector('input')) {
          targetCell.querySelector('input').focus(); return
        }
        if (targetCell.querySelector('.vxe-cell--label')) { // 只有点击后才会有输入框的单元格
          targetCell.querySelector('.vxe-cell--label').click(); return
        }
      }
    }
  }
  // 方向右键 39
  if (e.keyCode === 39 || e.keyCode === 9) {  // tab键在表格上与右键效果基本相似,可等同
    if (currCell.column >= maxTd) return
    for (let index = 0; index < 521; index++) {
      currCell.column++
      let targetCell = document.querySelector(`tr[rowid=row_${currCell.row}]`).querySelector(`.col_${currCell.column}`)
      if (targetCell) {
        if (targetCell.querySelector('input')) {
          targetCell.querySelector('input').focus(); return
        }
        if (targetCell.querySelector('.vxe-cell--label')) {
          targetCell.querySelector('.vxe-cell--label').click(); return
        }
      }
    }
  }
  // 方向上键 38
  if (e.keyCode === 38) {
    if (currCell.row <= minTr) return
    for (let index = 0; index < 1314; index++) {
      currCell.row--
      let targetRow = document.querySelector(`tr[rowid=row_${currCell.row}]`)
      if (targetRow) {  // 如果当前行都不存在,再查列会直接报错
        let targetCell = document.querySelector(`tr[rowid=row_${currCell.row}]`).querySelector(`.col_${currCell.column}`)
        if (targetCell) {
          if (targetCell.querySelector('input')) {
            targetCell.querySelector('input').focus(); return
          }
          if (targetCell.querySelector('.vxe-cell--label')) {
            targetCell.querySelector('.vxe-cell--label').click(); return
          }
        }
      }
    }
  }
  // 方向下键 40
  if (e.keyCode === 40) {
    if (currCell.row >= maxTr) return
    for (let index = 0; index < 9999; index++) {
      currCell.row++
      let targetRow = document.querySelector(`tr[rowid=row_${currCell.row}]`)
      if (targetRow) {
        let targetCell = document.querySelector(`tr[rowid=row_${currCell.row}]`).querySelector(`.col_${currCell.column}`)
        if (targetCell) {
          if (targetCell.querySelector('input')) {
            targetCell.querySelector('input').focus(); return
          }
          if (targetCell.querySelector('.vxe-cell--label')) {
            targetCell.querySelector('.vxe-cell--label').click(); return
          }
        }
      }
    }
  }
  currCell = _currCell; return  // 如果跳转的不是输入框,就赋回给初始值
}
export { cellClickEvent, keyDown }

四个 if 里面都有一些公共代码,本来想在for循环里面加方向键的判断,但一想想性能可能会不好,就算了。

for 循环的循环次数看自己表格中缺失(删除或隐藏)的行列多少了,一般设置10以内就够了(别告诉我你喜欢中间隐藏 1 千条 (°ˊДˋ°) )

关于点击后才会生成 input 框的单元格,大家可以看下这图:

如果大家发现明明跳转的是可生成 input 框的单元格,但就是没有跳转,那可能是这行渲染代码没有加上:        editRender: { name: "input" }

温馨提示:我这个代码没有实现在最左边单元格向左移动,自动跳转到上一行最右边那个单元格的效果,因为我感觉这样太飘了(反正我是不会觉得我菜)

要使用vxe-table和sortable实现表格列的左右拖拽,可以按照以下步骤进行: 1. **安装必要的库**: 首先,确保你已经安装了vxe-table和sortablejs。 ```bash npm install vxe-table sortablejs ``` 2. **引入必要的模块**: 在你的Vue组件中,引入vxe-table和sortablejs。 ```javascript import Vue from 'vue' import 'vxe-table/lib/style.css' import VXETable from 'vxe-table' import Sortable from 'sortablejs' Vue.use(VXETable) ``` 3. **创建Vue组件**: 创建一个Vue组件,并在其中定义vxe-table。 ```vue <template> <vxe-table :data="tableData" :columns="tableColumns" ref="xTable"> </vxe-table> </template> <script> export default { data() { return { tableData: [ { id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'vxe-table 从入门到放弃' }, { id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' }, { id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' }, { id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 23, address: 'vxe-table 从入门到放弃' }, { id: 10005, name: 'Test5', role: 'Develop', sex: 'Women', age: 30, address: 'Shanghai' }, { id: 10006, name: 'Test6', role: 'Designer', sex: 'Women', age: 21, address: 'vxe-table 从入门到放弃' }, { id: 10007, name: 'Test7', role: 'Test', sex: 'Man', age: 29, address: 'vxe-table 从入门到放弃' }, { id: 10008, name: 'Test8', role: 'Develop', sex: 'Man', age: 35, address: 'vxe-table 从入门到放弃' } ], tableColumns: [ { field: 'id', title: 'ID', width: 100 }, { field: 'name', title: 'Name', width: 200 }, { field: 'role', title: 'Role', width: 200 }, { field: 'sex', title: 'Sex', width: 100 }, { field: 'age', title: 'Age', width: 100 }, { field: 'address', title: 'Address', width: 300 } ] } }, mounted() { this.$nextTick(() => { this.setupSortable() }) }, methods: { setupSortable() { const xTable = this.$refs.xTable const tbody = xTable.$el.querySelector('.vxe-table--body tbody') Sortable.create(tbody, { onEnd: evt => { const { oldIndex, newIndex } = evt const currData = [...this.tableData] const [removed] = currData.splice(oldIndex, 1) currData.splice(newIndex, 0, removed) this.tableData = currData } }) } } } </script> ``` 4. **解释代码**: - **数据定义**:定义了一个表格数据和列配置。 - **mounted生命周期钩子**:在组件挂载后,调用`setupSortable`方法。 - **setupSortable方法**:使用sortablejs创建一个可拖拽的表格体,并在拖拽结束后更新表格数据。 通过以上步骤,你就可以实现vxe-table表格列的左右拖拽功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值