我有一个输入表单,它允许我从多个选项中进行选择,并在用户更改选择时执行一些操作。例如,

<select onChange="javascript:doSomething();">
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

现在,doSomething()只在选择改变时被触发。

我想在用户选择任何选项时触发doSomething(),可能是相同的选项。

我已经尝试使用“onClick”处理程序,但在用户开始选择过程之前被触发。

那么,是否有一种方法在用户每次选择时触发一个函数?

更新:

Darryl提出的答案似乎有效,但并不总是有效。有时,当用户单击下拉菜单时,甚至在用户完成选择过程之前,事件就会被触发!


当前回答

几个月前我做设计的时候也遇到了同样的问题。我发现的解决方案是在你正在使用的元素上使用.live("change", function())结合.blur()。

如果你想让它在用户点击时做一些事情,而不是改变,只需用点击替换改变。

我为我的下拉菜单分配了一个ID,选择并使用如下:

$(function () {
    $("#selected").live("change", function () {

    // do whatever you need to do

    // you want the element to lose focus immediately
    // this is key to get this working.
    $('#selected').blur();
    });
});

我看到这个问题没有选择答案,所以我想我应该给出我的建议。这对我来说非常有效,所以希望其他人在遇到困难时可以使用这段代码。

http://api.jquery.com/live/

编辑:使用on选择器而不是.live。参见jQuery .on()

其他回答

请注意,IE上的OPTION标签不支持事件处理程序,我想出了这个解决方案,尝试一下,给我你的反馈:

<script>
var flag = true;
function resetIndex(selObj) {
    if(flag) selObj.selectedIndex = -1;
    flag = true;
}
function doSomething(selObj) {
    alert(selObj.value)
    flag = false;
}
</script>
<select onchange="doSomething(this)" onclick="resetIndex(this)">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>

我在这里所做的实际上是重置选择索引,这样onchange事件就会一直被触发,当你点击时,我们会失去所选的项目,如果你的列表很长,这可能会很烦人,但它可能在某种程度上帮助你。

我要扩展一下jitbit的答案。当你点击下拉菜单,然后不选择任何东西就关闭下拉菜单时,我觉得很奇怪。最后得出了如下结论:

var lastSelectedOption = null; DDChange = function(Dd) { //Blur after change so that clicking again without //losing focus re-triggers onfocus. Dd.blur(); //The rest is whatever you want in the change. var tcs = $("span.on_change_times"); tcs.html(+tcs.html() + 1); $("span.selected_index").html(Dd.prop("selectedIndex")); return false; }; DDFocus = function(Dd) { lastSelectedOption = Dd.prop("selectedIndex"); Dd.prop("selectedIndex", -1); $("span.selected_index").html(Dd.prop("selectedIndex")); return false; }; //On blur, set it back to the value before they clicked //away without selecting an option. // //This is what is typically weird for the user since they //might click on the dropdown to look at other options, //realize they didn't what to change anything, and //click off the dropdown. DDBlur = function(Dd) { if (Dd.prop("selectedIndex") === -1) Dd.prop("selectedIndex", lastSelectedOption); $("span.selected_index").html(Dd.prop("selectedIndex")); return false; }; <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <select id="Dd" onchange="DDChange($(this));" onfocus="DDFocus($(this));" onblur="DDBlur($(this));"> <option>1</option> <option>2</option> </select> <br/> <br/>Selected index: <span class="selected_index"></span> <br/>Times onchange triggered: <span class="on_change_times">0</span>

这对用户来说更有意义,并且允许JavaScript在每次选择任何选项(包括先前的选项)时运行。

这种方法的缺点是,它破坏了在下拉菜单上使用tab键并使用方向键选择值的功能。这对我来说是可以接受的,因为所有用户都会一直点击所有内容,直到永恒结束。

这是我的解,和这里的解完全不同。它使用鼠标位置来确定是否单击了某个选项,而不是单击选择框打开下拉菜单。它利用事件。屏幕y位置,因为这是唯一可靠的跨浏览器变量。必须首先附加悬停事件,以便在单击事件之前计算出控件相对于屏幕的位置。

var select = $("select");

var screenDif = 0;
select.bind("hover", function (e) {
    screenDif = e.screenY - e.clientY;
});
select.bind("click", function (e) {
    var element = $(e.target);
    var eventHorizon = screenDif + element.offset().top + element.height() - $(window).scrollTop();
    if (e.screenY > eventHorizon)
        alert("option clicked");
});

这是我的jsFiddle http://jsfiddle.net/sU7EV/4/

这可能不能直接回答你的问题,但这个问题可以通过简单的设计调整来解决。我知道这可能不是100%适用于所有用例,但我强烈建议您重新考虑您的应用程序的用户流程,以及以下设计建议是否可以实现。

我决定做一些简单的事情,而不是黑客onChange()使用其他事件的替代方案,这并不是真正意义上的目的(模糊,点击等)。

我的解决方法是:

只需预先挂起一个没有任何值的占位符选项标记,如select。

所以,不要只使用下面的结构,这需要一些hack-y替代方案:

<select>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

考虑使用这个:

<select>
  <option selected="selected">Select...</option>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

因此,通过这种方式,您的代码更加简化,并且每当用户决定选择默认值以外的内容时,onChange将按预期工作。如果您不希望他们再次选择第一个选项,甚至可以将disabled属性添加到第一个选项,并强制他们从选项中选择一些内容,从而触发onChange()触发。

At the time of this answer, I'm writing a complex Vue application and I found that this design choice has simplified my code a lot. I spent hours on this problem before I settled down with this solution and I didn't have to re-write a lot of my code. However, if I went with the hacky alternatives, I would have needed to account for the edge cases, to prevent double firing of ajax requests, etc. This also doesn't mess up the default browser behaviour as a nice bonus (tested on mobile browsers as well).

有时候,你只需要退一步,从大局出发,寻找最简单的解决方案。

关于select标记(在这个场景中)的奇妙之处在于它将从选项标记中获取它的值。

Try:

<select onChange="javascript:doSomething(this.value);">
<option value="A">A</option>
<option value="B">B</option>
<option value="Foo">C</option>
</select>

对我来说还不错。