You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

原生JS:为何keydown事件中我的函数无法运行?

问题解决:按下Enter键触发表格新增行

原代码核心问题

  1. 每次调用addRow()都会给window重复绑定keydown事件,导致按一次Enter触发多次回调
  2. 直接调用onRowChange()时未传递事件对象e,函数内e.target会报错,逻辑无法执行
  3. 全局监听未判断触发场景,任何地方按Enter都会触发新增行逻辑

修改方案

  • 将keydown事件移到全局,仅绑定一次,避免重复绑定
  • 在事件回调中判断触发元素是否为表格内的输入框,且按下的是Enter键
  • 调整onRowChange逻辑,直接通过触发的输入框定位当前行,确保输入验证正常执行

修正后的完整代码

JavaScript

const table = document.querySelector('#table');
const addRowButton = document.querySelector('#addRow');

let firstNamesArray = [];
let lastNamesArray = [];
let rowNumber = 0;

function addRow() {
    let row = table.insertRow(-1);
    let cell1 = row.insertCell(0);
    let cell2 = row.insertCell(1);
    let firstNameInput = document.createElement("input");
    let lastNameInput = document.createElement("input");

    firstNameInput.type = "text";
    firstNameInput.setAttribute('id', `firstName${rowNumber}`);
    cell1.appendChild(firstNameInput);
        
    lastNameInput.type = "text";
    lastNameInput.setAttribute('id', `lastName${rowNumber}`);
    cell2.appendChild(lastNameInput);
}

function onRowChange(targetInput) {
    // 获取当前输入框所在的行
    const currentRow = targetInput.parentNode.parentNode;
    // 检查当前行两个输入框是否都有值
    const inputs = currentRow.querySelectorAll('input');
    const allFilled = [...inputs].every(input => input.value.trim() !== '');
    
    if (allFilled) {
        createNames(rowNumber);
        rowNumber++;
        addRow();
    }
}

function createNames(index) {
    let firstName = document.getElementById(`firstName${index}`).value;
    let lastName = document.getElementById(`lastName${index}`).value;
    firstNamesArray.push(firstName);
    lastNamesArray.push(lastName);
}

// 全局仅绑定一次keydown事件
window.addEventListener('keydown', (event) => {
    if (event.key === 'Enter') {
        // 阻止Enter默认行为(如表单提交)
        event.preventDefault();
        // 判断触发元素是否为表格内的输入框
        if (event.target.tagName === 'INPUT' && event.target.closest('#table')) {
            onRowChange(event.target);
        }
    }
}, false);

addRowButton.addEventListener('click', () => {
    addRow();
    addRowButton.disabled = true;
});

CSS

table {
    text-align: center;
    align-items: center;
    border: 1px solid black;
    border-collapse: collapse;
}

th {
    width: 50vmin;
    height: 10vmin;
    font-size: 20pt;
    font-weight: 800;
}

input {
    width: 50vmin;
    height: 5vmin;
    text-align: center;
    align-items: center;
    font-size: 18pt;
    font-weight: 400;
    font-family: Georgia, 'Times New Roman', Times, serif;
    border: 0;
    padding: 0;
}

HTML

<html>
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="styles.css">
    </head>

    <body>
        <article id="input-article">
            <table id="table" border="1">
                <tr>
                    <th>First Name:</th>
                    <th>Last Name:</th>
                </tr>
            </table> <br>

            <div id="buttons">
                <button id="addRow">Add Row</button>
                <button id="submit">Submit</button>
            </div>
        </article>

        <script src="app.js"></script>
    </body>
</html>

关键修改说明

  1. 事件绑定优化:全局仅绑定一次keydown事件,避免重复绑定导致的多次触发
  2. 场景判断:仅在表格内的输入框按下Enter时才执行新增逻辑,避免全局误触发
  3. 逻辑简化:通过触发的输入框直接定位当前行,输入验证逻辑更可靠
  4. 默认行为阻止:添加event.preventDefault()避免Enter键触发表单默认提交

内容的提问来源于stack exchange,提问作者That New Coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 21:47:15