基于antd的table,通过键盘的上下左右操作,进行input焦点切换

490 阅读1分钟

一:首先从antd中引入table,基于onRowClick监听事件

import { Table } from 'antd'
<Table
    columns={this.columns}
    dataSource={datalist.toJS()}
    onRowClick={this.handleKeydown} // 具体键盘操作事件
/>

二:handleKeydown的具体事件执行

handleKeydown = (record, index, event) => {
        // 类型为INPUT类型时监听
        if (event.target.tagName === 'INPUT') {
            // 根据当前获取焦点的input,找到最近的tr标签
            const currentTr = event.target.parentElement.closest('tr')
            // 根据当前获取焦点的input,找到最近的td标签
            const currentTd = event.target.parentElement.closest('td')
            // 根据当前获取焦点的input,找到最近的table标签
            const tableDom = event.target.parentElement.closest('table')
            // 通过table找到tbody
            const tbodyDom = tableDom.querySelector('tbody')
            // 获取tr整个长度
            const trLength = currentTr.children.length - 1
            // 获取td整个长度
            const tdLength = this.props.datalist.size - 1
            let colVal = Array.prototype.indexOf.call(currentTr.children, currentTd) // 列
            let rowVal = index // 行
            tableDom.onkeydown = (e) => {
                const codeVal = e.keyCode
                if (codeVal === 37) {
                    colVal--
                    // 如果找不到当前input循环找下一列input
                    const { newColVal } = this.whileAdd('colVal', 'reduce', tbodyDom, rowVal, colVal)
                    colVal = (newColVal < 0 ? 0 : newColVal)
                } else if (codeVal === 38) {
                    rowVal--
                    // 如果找不到当前input循环找下一行input
                    const { newRowVal } = this.whileAdd('rowVal', 'reduce', tbodyDom, rowVal, colVal)
                    rowVal = (newRowVal < 0 ? 0 : newRowVal)
                } else if (codeVal === 39) {
                    colVal++
                    const { newColVal } = this.whileAdd('colVal', 'add', tbodyDom, rowVal, colVal)
                    colVal = (newColVal > trLength ? trLength : newColVal)
                } else if (codeVal === 40) {
                    rowVal++
                    const { newRowVal } = this.whileAdd('rowVal', 'add', tbodyDom, rowVal, colVal)
                    rowVal = (newRowVal > tdLength ? tdLength : newRowVal)
                }
                // 执行获取焦点,并且文本框文字被选中操作
                this.handleMove(tbodyDom, rowVal, colVal)
            }
        }
    }

三:whileAdd的具体事件执行

 whileAdd = (type, operateType, tbodyDom, rowVal, colVal) => {
        const tdDom = tbodyDom.childNodes[rowVal] && tbodyDom.childNodes[rowVal].childNodes[colVal]
        const inputDom = tdDom ? tdDom.querySelector('input') : 'noTdDom'
        if (!inputDom) {
            if (operateType === 'reduce') {
                (type === 'rowVal') ? (rowVal--) : colVal--
            } else {
                (type === 'rowVal') ? rowVal++ : colVal++
            }
            // 递归执行
            this.whileAdd(type, operateType, tbodyDom, rowVal, colVal)
        }
        return {
            newRowVal: rowVal,
            newColVal: colVal,
        }
    }

四:handleMove的具体事件执行

handleMove = (tbodyDom, rowVal, colVal) => {
        const tdDom = tbodyDom.childNodes[rowVal].childNodes[colVal]
        const inputDom = tdDom.querySelector('input')
        if (inputDom) {
            // 由于dom渲染有时间差,用setTimeout包裹,等渲染完执行获取焦点和select
            setTimeout(() => {
                inputDom.focus()
                inputDom.select()
            }, 0);
        }
    }