动态创建元素时getElementById失效及表格交互问题求助
动态表格事件绑定与回车交互问题解决
问题描述
根据矩阵单元格数量生成带输入框的表格,遇到两个核心问题:
- 动态创建的输入框无法触发预先绑定的
focus和keyup事件 - 回车键切换输入框焦点、最后单元格回车新增行的功能存在异常
原代码
HTML代码
<!DOCTYPE html> <html lang="en"> <head > <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="src/style.css"> </head> <body onload="tableCreate()"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script> <script src="src/script.js"></script> </body> </html>
JavaScript代码
var c = [ ['casa', 'casa1', 'casa2'], ['casa3', 'casa4', 'casa5'], ['casa6', 'casa7', 'casa8'], ['casa9', 'casa10', 'casa11'], ]; function tableCreate() { const body = document.body, tbl = document.createElement('table'); tbl.setAttribute('id', 'tab_1'); tbl.style.width = '100px'; tbl.style.border = '1px solid red'; for (let i = 0; i < c.length; i++) { const tr = tbl.insertRow(); for (let j = 0; j < 3; j++) { const td = tr.insertCell(); var x = document.createElement('INPUT'); x.setAttribute('type', 'number'); x.setAttribute('class', 'username'); td.appendChild(x); td.style.border = '2px solid yellow'; } } document.body.appendChild(tbl); } $('.username').focus(function (event) { console.log('gd'); }); var currentBoxNumber = 0; $('.username').keyup(function (event) { if (event.keyCode == 13) { textboxes = $('input.username'); console.log('o'); currentBoxNumber = textboxes.index(this); if (textboxes[currentBoxNumber + 1] != null) { nextBox = textboxes[currentBoxNumber + 1]; nextBox.focus(); nextBox.select(); event.preventDefault(); } else { const bd = document.body, tbl = document.getElementById('tab_1'); const tr = tbl.insertRow(); for (let j = 0; j < 3; j++) { const td = tr.insertCell(); var x = document.createElement('INPUT'); x.setAttribute('type', 'number'); x.setAttribute('class', 'username'); td.style.border = '2px solid green'; td.appendChild(x); } bd.appendChild(tbl); } return false; } });
解决方案
1. 采用事件委托绑定动态元素事件
直接通过.username绑定事件只能作用于页面加载时已存在的元素,动态新增的元素需要用事件委托,将事件绑定到父级(或更上层的静态元素),确保后续创建的元素也能触发事件:
// 绑定focus事件 $(document).on('focus', '.username', function(event) { console.log('gd'); }); // 绑定keyup事件 var currentBoxNumber = 0; $(document).on('keyup', '.username', function(event) { if (event.keyCode === 13) { const textboxes = $('input.username'); currentBoxNumber = textboxes.index(this); // 切换到下一个输入框 if (currentBoxNumber + 1 < textboxes.length) { const nextBox = textboxes.eq(currentBoxNumber + 1); nextBox.focus(); nextBox.select(); event.preventDefault(); } else { // 新增一行并聚焦第一个输入框 const tbl = document.getElementById('tab_1'); const tr = tbl.insertRow(); let newInput; for (let j = 0; j < 3; j++) { const td = tr.insertCell(); const x = document.createElement('INPUT'); x.setAttribute('type', 'number'); x.setAttribute('class', 'username'); td.style.border = '2px solid green'; td.appendChild(x); // 记录新行的第一个输入框 if (j === 0) { newInput = x; } } // 聚焦新行的第一个输入框 newInput.focus(); } return false; } });
2. 优化核心逻辑细节
- 新增行时无需重复执行
bd.appendChild(tbl),表格已存在于DOM中 - 用
textboxes.eq(currentBoxNumber + 1)替代数组索引访问,更符合jQuery操作规范 - 新增行后自动聚焦到新行的第一个输入框,提升交互流畅度
修改后的完整JavaScript代码
var c = [ ['casa', 'casa1', 'casa2'], ['casa3', 'casa4', 'casa5'], ['casa6', 'casa7', 'casa8'], ['casa9', 'casa10', 'casa11'], ]; function tableCreate() { const body = document.body, tbl = document.createElement('table'); tbl.setAttribute('id', 'tab_1'); tbl.style.width = '100px'; tbl.style.border = '1px solid red'; for (let i = 0; i < c.length; i++) { const tr = tbl.insertRow(); for (let j = 0; j < 3; j++) { const td = tr.insertCell(); var x = document.createElement('INPUT'); x.setAttribute('type', 'number'); x.setAttribute('class', 'username'); td.appendChild(x); td.style.border = '2px solid yellow'; } } document.body.appendChild(tbl); } // 事件委托绑定focus事件 $(document).on('focus', '.username', function(event) { console.log('gd'); }); var currentBoxNumber = 0; // 事件委托绑定keyup事件 $(document).on('keyup', '.username', function(event) { if (event.keyCode === 13) { const textboxes = $('input.username'); currentBoxNumber = textboxes.index(this); if (currentBoxNumber + 1 < textboxes.length) { const nextBox = textboxes.eq(currentBoxNumber + 1); nextBox.focus(); nextBox.select(); event.preventDefault(); } else { const tbl = document.getElementById('tab_1'); const tr = tbl.insertRow(); let newFirstInput; for (let j = 0; j < 3; j++) { const td = tr.insertCell(); const x = document.createElement('INPUT'); x.setAttribute('type', 'number'); x.setAttribute('class', 'username'); td.style.border = '2px solid green'; td.appendChild(x); if (j === 0) { newFirstInput = x; } } newFirstInput.focus(); } return false; } });
内容的提问来源于stack exchange,提问作者Emilio Pantanali
相关产品推荐
相关产品推荐

