当我使用val()设置select的值时,为什么jquery change事件没有触发?


377

change()当通过设置值时,不会运行事件处理程序中的逻辑val(),但是当用户用鼠标选择一个值时,它确实会运行。为什么是这样?

<select id="single">
    <option>Single</option>
    <option>Single2</option>
</select>

<script>
    $(function() {
        $(":input#single").change(function() {
           /* Logic here does not execute when val() is used */
        });
    });

    $("#single").val("Single2");
</script>

Answers:


589

因为该change事件需要由用户而不是通过javascript代码启动的实际浏览器事件。

改为这样做:

$("#single").val("Single2").trigger('change');

要么

$("#single").val("Single2").change();

1
嗨,进行此更新下拉列表。但是递归调用onChange()。
Pankaj 2014年

3
我挖掘这个答案。它可以工作,但是jQuery是否没有更好的方法?我敢肯定,每次我们更改设置了更改处理程序的值(讽刺)时,我们都会记住这样做。使用数据绑定的框架可能会更好地解决这个问题?
杰西2015年

@ user113716您会知道如何在不知道任何值的情况下进行虎tig吗?
BKSpurgeon '16

4
我同意这是正确的答案,但这绝对糟透了我想要做的事情。
达斯汀·普桑桑

试试$(“#single”)。trigger({type:“ change”,val:“ Single2”})
user2901633

44

我相信您可以通过以下方式手动触发更改事件trigger()

$("#single").val("Single2").trigger('change');

尽管为什么它不会自动启动,但我不知道。


我不能工作,也$(“#single”)。val(“ Single2”)。change(); 我正在动态创建下拉列表并更改其值(它对我来说很好),但是当我尝试触发更改时,它对我不起作用。
Maneesh Kumar 2013年

4
“位”延迟,但不会自动触发,因为这会导致无限循环。思考$('#foo').change(function() { $( this ).val( 'whatever' ); });
JJJ

@Juhana我认为无限循环比val()神秘地未能触发“更改”绑定要容易注意到,诊断和修复。
iono

调用.change()是调用.trigger('change')的简写。
Triynko '16

9

在val()之后添加这段代码似乎可行:

$(":input#single").trigger('change');

6
是的,但是您无需使用进行单独的DOM选择$(":input#single")。实际上,您实际上不应该这样做。只是链后.val()。您可以使用.trigger('change').change()。它们是完全相同的。
user113716 2011年

8

据我所读的API。仅当用户单击选项时才触发该事件。

http://api.jquery.com/change/

对于选择框,复选框和单选按钮,当用户使用鼠标进行选择时会立即触发该事件,但是对于其他元素类型,该事件将推迟到该元素失去焦点之前。


其他元素类型有哪些替代方案?我希望对input元素立即触发“ change”事件,而不是在元素失去焦点时触发。你知道吗?
Dan Nissenbaum 2015年

1
如果“立即”的意思是“每当在输入中按下一个键”,则是在查找onkeyup,onkeypress和onkeydown事件,而不是onchange。
user2867288 '16

6

为了使其更容易,添加一个自定义函数并在需要时随时调用它,更改值也会触发更改

$.fn.valAndTrigger = function (element) {
    return $(this).val(element).trigger('change');
}

$("#sample").valAndTirgger("NewValue");

或者您可以覆盖val函数以始终在调用val时调用更改

(function ($) {
    var originalVal = $.fn.val;
    $.fn.val = function (value) {
        this.trigger("change");
        return originalVal.call(this, value);
    };
})(jQuery);

样本位于http://jsfiddle.net/r60bfkub/


我的浏览器抱怨递归过多,对此有何解决办法?
巴尔加夫Nanekalva '17

您正在侦听change某个控件上的-event并执行(直接或间接)再次触发change同一控件上的-event 的回调。我建议您为手动触发的事件使用另一个名称(例如explicit.change),这样它就不会重新触发change-event,防止循环,并且仍然允许您对事件做出反应。
卡马菲瑟

3

如果您不想与默认更改事件混淆,可以提供自定义事件

$('input.test').on('value_changed', function(e){
    console.log('value changed to '+$(this).val());
});

触发设置值的事件,您可以

$('input.test').val('I am a new value').trigger('value_changed');

3

在将CMB2与Wordpress一起使用时,我遇到了相同的问题,并想了解文件上传元框的change事件。

因此,如果您无法修改调用更改的代码(在本例中为CMB2脚本),请使用下面的代码。设置值后将调用触发器,否则您的更改eventHandler将起作用,但该值将是前一个值,而不是被设置的值。

这是我使用的代码:

(function ($) {
    var originalVal = $.fn.val;
    $.fn.val = function (value) {
        if (arguments.length >= 1) {
            // setter invoked, do processing
            return originalVal.call(this, value).trigger('change');
        }
        //getter invoked do processing
        return originalVal.call(this);
    };
})(jQuery);

很好,但是您可以显示如何将其限制为仅一个特定输入吗?
jwebb

@jwebb不太清楚您的意思吗?我们重写了jQuery val()函数。您将更改事件处理程序绑定到特定输入。
user2075039

我的意思是@ user2075039,如果使用jQuery val()函数在页面上有多个输入并且您不想将自定义更改事件处理程序绑定到所有输入,而只是其中之一,该怎么办?
jwebb

@jwebb你可以检查 this.selector在覆盖$.fn.val函数内部特定的选择器(取决于选择器所使用的内容)。这是我发现最好的方法,它仅适用于特定领域,唯一的问题是您必须知道它们用于选择器
sMyles

1
$(":input#single").trigger('change');

这适用于我的脚本。我有3个连击并与chainSelect事件绑定,我需要通过url传递3个值并默认选择全部下拉菜单。我用这个

$('#machineMake').val('<?php echo $_GET['headMake']; ?>').trigger('change');

第一次活动奏效了。


10
希望您永远不要在现实世界中这样做。不用说$ _GET ['whatever']不能被信任。
Denis V

1

如果您刚刚将选择选项添加到表单中,并且希望触发更改事件,那么我发现需要setTimeout,否则jQuery不会选择新添加的选择框:

window.setTimeout(function() { jQuery('.languagedisplay').change();}, 1);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.