jQuery实现HTML表格行键盘导航:回车键功能失效求助
表格键盘导航回车键功能修复
我有一个Ajax渲染的HTML表格,希望通过上下箭头键导航表格行,按回车键勾选当前选中行的单选按钮。目前上下箭头导航正常,但回车键功能失效。
表格HTML代码
<table class="table" id="tbl_byKeyboard"> <thead> <tr> <th>#</th> <th>Date</th> <th>Customer</th> <th>Discount</th> <th>Total</th> </tr> </thead> <tbody> <tr> <td> <input type="radio" name="bid" value="122"> </td> <td>2022-10-01</td> <td>Customer 01</td> <td>10%</td> <td>1000.00</td> </tr> <tr> <td> <input type="radio" name="bid" value="123"> </td> <td>2022-10-01</td> <td>Customer 02</td> <td>10%</td> <td>2000.00</td> </tr> <tr> <td> <input type="radio" name="bid" value="124"> </td> <td>2022-10-01</td> <td>Customer 03</td> <td>10%</td> <td>3000.00</td> </tr> </tbody> </table>
原jQuery代码
$(document).ready(function() { $(document).on('click', "#tbl_byKeyboard tbody tr", function(e) { var inp = this.querySelector('input') if (inp == null) return if (e.target.tagName != "INPUT") { inp.checked = !inp.checked } $('#tbl_byKeyboard tbody tr').removeClass('active'); $(this).addClass('active'); }) }); $(window).on('keydown', tbl_navigate) function tbl_navigate(e) { var $tbl = $('#tbl_byKeyboard'); var $cur = $('.active', $tbl).removeClass('active').first(); if (e.keyCode === 40) { //down if ($cur.length) { $cur.next().addClass('active'); } else { $tbl.children().first().addClass('active'); } } else if (e.keyCode == 38) { //up if ($cur.length) { $cur.prev().addClass('active'); } else { $tbl.children().last().addClass('active'); } } else if (e.keyCode == 13) { //enter var $this = $cur; var inp = $this.find('input') if (inp == null) return if (inp.is(':checked')) { inp.prop('checked', false); } else { inp.prop('checked', true); $('#tbl_byKeyboard tbody tr').removeClass('active'); $this.addClass('active'); } } }
问题原因分析
- active行范围错误:原代码
$('.active', $tbl)会匹配表格内所有带active类的元素,包括thead的行,但我们只需要tbody中的数据行。 - 回车键逻辑顺序错误:函数开头就移除了
$cur的active类,导致回车键处理时无法正确定位当前选中行。 - 默认行选择错误:方向键默认选中的是整个表格的第一/最后一行(即thead的行),而非tbody的数据行。
- 单选按钮逻辑冗余:同一name的单选按钮组会自动取消其他选项的选中状态,无需手动处理取消逻辑。
修复后的代码
$(document).ready(function() { $(document).on('click', "#tbl_byKeyboard tbody tr", function(e) { const inp = this.querySelector('input'); if (!inp) return; if (e.target.tagName !== "INPUT") { inp.checked = true; // 单选按钮直接设为选中,自动取消其他选项 } $('#tbl_byKeyboard tbody tr').removeClass('active'); $(this).addClass('active'); }); }); $(window).on('keydown', tbl_navigate); function tbl_navigate(e) { const $tbl = $('#tbl_byKeyboard'); const $tbodyRows = $tbl.find('tbody tr'); let $cur = $tbodyRows.filter('.active').first(); // 优先处理回车键逻辑 if (e.keyCode === 13) { // 无选中行时默认选中第一行 if (!$cur.length) { $cur = $tbodyRows.first().addClass('active'); } const inp = $cur.find('input'); if (inp.length) { inp.prop('checked', true); } return; // 回车键处理完成后直接返回,不执行方向键逻辑 } // 处理方向键:先移除当前active类 $cur.removeClass('active'); if (e.keyCode === 40) { // 下箭头 if ($cur.length) { $cur.next().length ? $cur.next().addClass('active') : $tbodyRows.first().addClass('active'); } else { $tbodyRows.first().addClass('active'); } } else if (e.keyCode === 38) { // 上箭头 if ($cur.length) { $cur.prev().length ? $cur.prev().addClass('active') : $tbodyRows.last().addClass('active'); } else { $tbodyRows.last().addClass('active'); } } }
关键改动说明
- 限定active行范围:使用
$tbodyRows.filter('.active')仅在tbody行中查找选中行,避免干扰thead。 - 调整回车键处理顺序:先处理回车键逻辑,再执行方向键逻辑,避免提前移除active类导致定位失败。
- 修正默认行选择:方向键默认选中tbody的第一/最后一行,而非整个表格的首尾行。
- 简化单选按钮逻辑:利用单选按钮组特性,直接设置
checked=true自动取消其他选项,减少冗余代码。 - 优化边界导航:导航到首尾行时循环跳转,提升键盘导航体验。
内容的提问来源于stack exchange,提问作者ugsgknt
相关产品推荐
相关产品推荐

