【问题标题】:How do I properly capture an onchange or onkeyup event for a dynamically inserted 'input' text element?如何正确捕获动态插入的“输入”文本元素的 onchange 或 onkeyup 事件?
【发布时间】:2012-04-01 13:11:46
【问题描述】:

我有一些 JavaScript 可以为我构建一些 HTML 并将其插入到 div 中。我正在使用 jQuery 1.7.2 进行此测试。

我有兴趣在名为 gene_autocomplete_fieldinput 文本字段上附加自定义更改或 keyup 事件处理程序。

这是我迄今为止尝试过的。

以下函数构建 HTML,将其插入到名为 gene_containerdiv 中:

function buildGeneContainerHTML(count, arr) {
    var html = "";
    // ...
    html += "<input type='text' size='20' value='' id='gene_autocomplete_field' name='gene_autocomplete_field' placeholder='Enter gene name...' /><br/>";
    // ...
    return html;
}

// ...
$('#gene_container').html( buildGeneContainerHTML(count, geneNameArr) );

在调用 HTML 时,我从 gene_container 元素中获取 gene_autocomplete_field,然后覆盖 gene_autocomplete_fieldkeyup 事件处理程序:

<script>
    $(document).ready(function() {
        $("#gene_container input:[name=gene_autocomplete_field]").live('keyup', function(event) {
            refreshGenePicker($("#gene_container input:[name=gene_autocomplete_field]").val());
        });
    });
</script>

当我更改 gene_autocomplete_field 中的文本时,refreshGenePicker() 函数只会发送警报:

function refreshGenePicker(val) {
    alert(val);
}

结果

如果我在gene_autocomplete_field 元素中键入任何字母,事件处理程序似乎会无限次调用alert(val)。我收到一个又一个警报,浏览器被对话框接管。返回的值是正确的,但我担心refreshGenePicker() 会被一遍又一遍地调用。我认为这不是正确的行为。

问题

  • 如何正确捕获一次keyup 事件,以便我只处理一次对自动完成字段的内容更改?
  • 我应该为此目的使用其他事件吗?

更新

事实证明,不仅仅是 13 的 keyCode(回车/回车)可能是一个问题——按下 Control、Alt、Esc 或其他特殊字符会触发一个事件(但不会出现症状,只要无限循环问题)。我过滤的基因名称中没有元字符。所以我使用alphanumeric detection test 过滤掉进一步事件处理中的非字母数字字符,其中包括返回键:

if (!alphaNumericCheck(event.keyCode)) return;

【问题讨论】:

标签: javascript jquery html events event-handling


【解决方案1】:

alert 被称为无限次,因为您使用“Enter”键来确认/关闭警报。请改用.on('change')。这将防止当您在 alert 中使用 enter 时调用 refreshGenePicker

不过,'change' 事件只会在输入元素失去焦点时触发。如果您想在每个键上使用refreshGenePicker,请改用以下方法:

$("#gene_container input:[name=gene_autocomplete_field]").live('keyup', function(event) {
    if(event.keyCode === 13) // filter ENTER
        return;
    refreshGenePicker($("#gene_container input:[name=gene_autocomplete_field]").val());
});

这将过滤任何传入的回车键事件 (jsFiddle demo)。同时切换到.on 并删除.live

编辑:请注意,关闭alert 模式的可能性更大,例如escapespace 键。您应该在 refreshGenePicker 中添加一个检查值是否实际更改

【讨论】:

  • Hmmmz 在什么浏览器上返回捕获的文本字段?无法在 Chrome 上重现。
  • 我正在测试 Safari 5.1.5 和 Chrome 18.0.1025.142。
  • 我在 Chrome 20 上也许就是这样。谢谢!但我仍然认为这是奇怪的行为,但是你要做什么:)
  • @RepWhoringPeeHaa:Windows 上的 Firefox 和 Opera 表现相同。 Internet Explorer 9 不关心它,但它有点慢(我可以在事件被触发之前键入 asdfghj)。事件传播在中断 JavaScript 方法中的乐趣(promptconfirmalert):)。
  • @Anthony: w3.org/TR/DOM-Level-3-Events/#dom-event-architecture - 但是,模态对话框被keydown 取消,它不等待按键信号。在第一个演示中自己尝试一下,只需按住 enter/esc/space。
【解决方案2】:

如果你使用的是 jQuery > 1.7,你真的应该使用 .on()

查看the perftest

还可以看看我的一些related question

另外,当测试相等时,你真的应该添加quotes around it

input:[name='gene_autocomplete_field']

回答你真正的问题:)。它不应该像您提供的代码那样表现。也许还有其他问题。你可以为这个问题设置一个 jsfiddle 吗?

查看my demo,也许您会发现您的代码有什么问题:

function refreshGenePicker(value) {
    console.log('keyup! Value is now: ' + value);
}

(function($) {
    var someHtml = '<input type="text" name="gene_autocomplete_field">';
    $('body').append(someHtml);

    $('body').on('keyup', 'input[name="gene_autocomplete_field"]', function(e) {
        refreshGenePicker($(this).val());
    });
})(jQuery);​

【讨论】:

    【解决方案3】:
    $(document).ready(function() {
        $('#test').html('<input id="text" />');
        $('#text').keyup(function() {
            console.log($(this).val());
        });
    });​
    

    这很好用。由于您在&lt;script&gt; 标记中获得了我们的第二个代码块,因此您可能会多次运行它——这将导致它多次绑定并在每次绑定时产生多个警报。您当然可以在添加 keyup 之前在该输入上使用 .unbind(),但我认为更好的解决方案是将所有代码分组到一个 $(document).ready(); 中,以确保您只绑定对象一次。

    http://jsfiddle.net/Ka7Ty/2/

    【讨论】:

    • 不,这不适用于动态插入的 HTML。这只有在 input 元素已经存在时才有效。
    猜你喜欢
    • 1970-01-01
    • 2016-10-03
    • 2017-01-01
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2022-01-09
    相关资源
    最近更新 更多