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

为何jQuery的rows.on("blur", handler)会触发handler无限循环调用?

jQuery blur事件无限重复触发的问题解决

问题描述

使用jQuery 3.6.1实现表单动态添加行功能,核心逻辑是:输入框失焦时检查是否存在三个输入框全为空的行,若不存在则添加新行。但实际运行时,聚焦name以compdiv开头的输入框后失焦,alert弹窗弹出,关闭后会无限重复触发,代码中无其他调用OSH.doDivisions()的逻辑。

初始核心代码:

OSH.setDivisions = function() {
    let rows = $("input[name^='compdiv']");
    rows.on("blur", OSH.doDivisions)
}

OSH.doDivisions = function() {
    alert("In doDivisions()");
    if (OSH.emptyDivisions() == 0) {
        OSH.addDivision();
    }
}

页面初始表格结构:

<tr>
    <td><input id="compdiv_name[]" name="compdiv_name[]" type="text" style="width:320px"/></td>
    <td><input id="compdiv_adult[]" name="compdiv_adult[]" type="text"  style="width:60px"/></td>
    <td><input id="compdiv_jr[]" name="compdiv_jr[]" type="text"  style="width:60px"/></td>
</tr>

后续补充的相关函数及初始化代码:

OSH.emptyDivisions = function() {
    let numempty = 0;
    let values = [];
    let rows = $("input[name^='compdiv']");
    for (let i = 0; i < rows.length; ++i) {
        if (rows[i].type != "text") {
            continue;
        }
        if (rows[i].name == "compdiv_name[]") {
            values[i] = rows[i].value;
            if (rows[i + 1].name == "compdiv_adult[]") {
                values[i] += rows[i + 1].value;
                if (rows[i + 2].name == "compdiv_jr[]") {
                    values[i] += rows[i + 2].value;
                    if (values[i] == "") {
                        ++numempty;
                        i += 2;
                    }
                }
            }
        }
    }
    return numempty;
}

OSH.addDivision = function() {
    let data = '\
        <tr>\
            <td><input id="compdiv_name[]" name="compdiv_name[]" type="text" style="width:320px"/></td>\
            <td><input id="compdiv_adult[]" name="compdiv_adult[]" type="text"  style="width:60px"/></td>\
            <td><input id="compdiv_jr[]" name="compdiv_jr[]" type="text"  style="width:60px"/></td>\
        </tr>\
    ';
    $("#lastDivision").before(data);
}

$(document).ready(OSH.setDivisions());

问题原因

  1. 事件绑定方式错误:$(document).ready(OSH.setDivisions())直接执行了函数而非传递引用,后续若误触发setDivisions会导致重复绑定,一次失焦触发多次回调。
  2. 未使用事件委托:直接给初始输入框绑定blur事件,新添加的输入框无法继承事件,且重复执行绑定逻辑会给已有元素叠加事件。
  3. alert干扰焦点状态:alert弹窗弹出时会强制输入框失焦,关闭后焦点异常跳转,可能触发额外的blur事件。
  4. 空行统计逻辑易出错:按输入框遍历的循环逻辑存在索引越界风险,可能导致空行统计错误,触发不必要的新行添加,间接引发事件异常。

解决方案

1. 修正DOM就绪事件的写法

传递函数引用给ready,确保仅在DOM就绪时执行一次绑定:

$(document).ready(OSH.setDivisions);

2. 使用事件委托绑定事件

将事件委托给表格父元素,新添加的输入框自动继承事件,避免重复绑定:

OSH.setDivisions = function() {
    // 替换为实际表格的选择器,比如表格id或tbody
    $("table").on("blur", "input[name^='compdiv']", OSH.doDivisions);
}

3. 优化空行统计逻辑

按行遍历统计,逻辑更清晰,避免索引错误:

OSH.emptyDivisions = function() {
    let numempty = 0;
    // 遍历包含目标输入框的每一行
    $("tr:has(input[name^='compdiv'])").each(function() {
        const nameVal = $(this).find("input[name='compdiv_name[]']").val().trim();
        const adultVal = $(this).find("input[name='compdiv_adult[]']").val().trim();
        const jrVal = $(this).find("input[name='compdiv_jr[]']").val().trim();
        // 三个输入框均为空时计数+1
        if (!nameVal && !adultVal && !jrVal) {
            numempty++;
        }
    });
    return numempty;
}

4. 替换alert为控制台日志调试

避免alert干扰焦点状态,改用console.log调试:

OSH.doDivisions = function() {
    console.log("In doDivisions()");
    if (OSH.emptyDivisions() == 0) {
        OSH.addDivision();
    }
}

内容的提问来源于stack exchange,提问作者sootsnoot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 08:07:00