HTML <select>是否有onSelect事件或等效事件?

ePh*_*aoh 198 html javascript html-select dom-events

我有一个输入表单,可以让我从多个选项中进行选择,并在用户更改选择时执行某些操作.例如,

<select onChange="javascript:doSomething();">
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
Run Code Online (Sandbox Code Playgroud)

现在,doSomething()只有在选择更改时才会触发.

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

我尝试过使用"onClick"处理程序,但在用户启动选择过程之前会触发该处理程序.

那么,有没有办法在用户的每次选择上触发一个功能?

更新:

达里尔建议的答案似乎有效,但它并不一致.有时,只要用户点击下拉菜单,即使在用户完成选择过程之前,事件也会被触发!

小智 83

这是最简单的方法:

<select name="ab" onchange="if (this.selectedIndex) doSomething();">
    <option value="-1">--</option>
    <option value="1">option 1</option> 
    <option value="2">option 2</option>
    <option value="3">option 3</option>
</select>
Run Code Online (Sandbox Code Playgroud)

同时使用鼠标选择和键盘向上/向下键可以选择聚焦.

  • 但是,当用户再次选择"同一个"时,这不会做任何事情,对吧? (33认同)
  • 这个答案有最多的赞成,但它没有解决问题!当用户选择已经选择的选项时,不会触发`doSomething()`函数.请参阅[plunk](http://plnkr.co/edit/Ir3r0wzk9hKwsKgvIThD?p=preview),其中背景颜色仅在您选择***选项时才会更改. (13认同)
  • 请注意,来自@KayZhu的注释只有一半是正确的:正确的做法是检查"selectedIndex"是否大于或等于零(或大于-1).没有"type()"函数,"selectedIndex"永远不会是"未定义". (3认同)
  • @TJCrowder你是对的 - 当我写下半场时不确定我在想什么.我删除了原始评论,为了不混淆他人,这里是原始评论(请注意前半部分是正确的,第二部分是错误的):*这对于第一个选项不起作用在JS中,索引0:0的值为false,因此doSomething()将不会被执行.相反,使用`if(type(this.selectedIndex)!= undefined; doSomething()`* (2认同)

Ale*_*lex 62

我需要完全一样的东西.这对我有用:

<select onchange="doSomething();" onfocus="this.selectedIndex = -1;">
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
Run Code Online (Sandbox Code Playgroud)

支持这个:

当用户选择任何选项时,可能再次选择相同的选项

  • 如果已经选择了某个值,则通过此选项卡将导致出现问题.一旦该字段被导航到该值将消失,这是一个非常意外的用户行为.此外,当你关闭标签时,即使你没有做任何类似的事情,你也会失去选择.否则,好主意. (6认同)
  • http://jsfiddle.net/ecmanaut/335XK/适用于osx Chrome 30,Safari 6,Firefox 17. (4认同)
  • 非常棒的小费.帮助我解决了无法选择第一个选项的问题 (3认同)
  • 也适用于Win8 IE10,Win7 IE9,Win7 IE8,WinXP IE7和IE6.Jsfiddle或IE恶作剧迫使您直接使用http://fiddle.jshell.net/ecmanaut/335XK/show/light/进行测试 - 他们的编辑器视图无法加载示例中使用的jQuery以提高可读性.以上所有仅通过鼠标交互测试; 为了使这个键盘友好,这个黑客可能需要额外的工作,因为至少旧的IE很高兴在您有机会选择"C"之前触发更改事件. (2认同)

Jam*_*oux 14

2022 普通 JavaScript

...因为这是 Google 上的热门搜索。

原始海报没有要求 JQuery 解决方案,但所有现有答案仅演示 JQuery 或内联 SELECT 标记事件。以下是使用 Vanilla Javascript 的方法:

将事件监听器与“ change ”事件结合使用。

const selectDropdown = document.querySelector('select');
selectDropdown.addEventListener('change', function (e) { /* your code */ });
Run Code Online (Sandbox Code Playgroud)

...或者调用一个单独的函数:

function yourFunc(e) { /* your code here */ }

const selectDropdown = document.querySelector('select');
selectDropdown.addEventListener('change', yourFunc);
Run Code Online (Sandbox Code Playgroud)


Cod*_*ody 11

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

如果您希望在用户只需点击而不是更改时执行某些操作,只需替换changeclick.

我为我的下拉列表分配了一个ID selected,并使用了以下内容:

$(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();
    });
});
Run Code Online (Sandbox Code Playgroud)

我看到这个没有选定的答案,所以我想我会给出我的意见.这对我来说非常有效,所以希望其他人在遇到困难时可以使用这些代码.

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

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

  • 这有助于解决问题中表达的问题,即在选择*更改*之前没有任何反应*? (7认同)
  • @LarsH 这个问题已经好几年了,不确定——我可能读错了这个问题并且感到困惑。 (2认同)

Dar*_*ein 7

只是一个想法,但是可以对每个<option>元素进行onclick 吗?

<select>
  <option onclick="doSomething(this);">A</option>
  <option onclick="doSomething(this);">B</option>
  <option onclick="doSomething(this);">C</option>
</select>
Run Code Online (Sandbox Code Playgroud)

另一个选择可能是在选择上使用onblur.当用户点击选择时,这将触发.此时,您可以确定选择了哪个选项.为了在正确的时间触发此操作,选项的onclick可能会使字段模糊(在jQuery中使其他活动或只是.blur()).

  • 在所有版本的IE中,将事件处理程序放在选项上都会失败!http://webbugtrack.blogspot.com/2007/11/bug-280-lack-of-events-for-options.html (8认同)
  • 也失败了铬:) (8认同)

小智 7

我知道这个问题现在已经很老了,但是对于仍然遇到这个问题的人来说,我已经通过在我自己的网站上通过向我的选项标记添加 onInput 事件来实现这一点,然后在该调用的函数中检索该选项输入的值。

<select id='dropdown' onInput='myFunction()'>
  <option value='1'>1</option>
  <option value='2'>2</option>
</select>

<p>Output: </p> 
<span id='output'></span>

<script type='text/javascript'>
function myFunction() {
 var optionValue = document.getElementById("dropdown").value;
 document.getElementById("output").innerHTML = optionValue;
}
</script>
Run Code Online (Sandbox Code Playgroud)

  • 好像不支持重新选择 (2认同)

小智 6

onclick方法并不完全糟糕,但如上所述,当鼠标点击不改变值时,它不会被触发.
但是,可以在onchange事件中触发onclick事件.

<select onchange="{doSomething(...);if(this.options[this.selectedIndex].onclick != null){this.options[this.selectedIndex].onclick(this);}}">
    <option onclick="doSomethingElse(...);" value="A">A</option>
    <option onclick="doSomethingElse(..);" value="B">B</option>
    <option onclick="doSomethingElse(..);" value="Foo">C</option>
</select>
Run Code Online (Sandbox Code Playgroud)


scu*_*ffe 5

如果你真的需要它像这样工作,我会这样做(以确保它可以通过键盘和鼠标工作)

  • 将 onfocus 事件处理程序添加到选择以设置“当前”值
  • 将 onclick 事件处理程序添加到选择以处理鼠标更改
  • 将 onkeypress 事件处理程序添加到选择以处理键盘更改

不幸的是,onclick 将运行多次(例如,在打开选择...和选择/关闭时)并且当没有任何变化时 onkeypress 可能会触发...

<script>
  function setInitial(obj){
    obj._initValue = obj.value;
  }
  function doSomething(obj){
    //if you want to verify a change took place...
    if(obj._initValue == obj.value){
      //do nothing, no actual change occurred...
      //or in your case if you want to make a minor update
      doMinorUpdate();
    } else {
      //change happened
      getNewData(obj.value);
    }
  }
</script>


<select onfocus="setInitial(this);" onclick="doSomething();" onkeypress="doSomething();">
  ...
</select>
Run Code Online (Sandbox Code Playgroud)


Jim*_*uck 5

要在用户每次选择某些内容时正确触发事件(即使是相同的选项),您只需要欺骗选择框。

就像其他人所说的那样,指定selectedIndex对焦点的否定以强制更改事件。虽然这确实允许您欺骗选择框,但只要它仍然具有焦点,它就无法工作。简单的解决方法是强制选择框模糊,如下所示。

标准 JS/HTML:

<select onchange="myCallback();" onfocus="this.selectedIndex=-1;this.blur();">
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
Run Code Online (Sandbox Code Playgroud)

jQuery 插件:

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

<script type="text/javascript">
    $.fn.alwaysChange = function(callback) {
        return this.each(function(){
            var elem = this;
            var $this = $(this);

            $this.change(function(){
                if(callback) callback($this.val());
            }).focus(function(){
                elem.selectedIndex = -1;
                elem.blur();
            });
        });
    }


    $('select').alwaysChange(function(val){
        // Optional change event callback,
        //    shorthand for $('select').alwaysChange().change(function(){});
    });
</script>
Run Code Online (Sandbox Code Playgroud)

您可以在此处查看工作演示

  • 这样做的问题是它会破坏当前的选择。如果当前选择是 B 并且我单击下拉菜单,复选标记将显示在 A 旁边!但 A 并未真正被选中,因为如果我滑出菜单并释放鼠标按钮(中止菜单),选择就会变为空白。如果您按 Tab 键切换到下拉菜单,则选择也会变为空白,如果您按 Tab 键切换到表单的其他部分,并且不希望在此过程中造成任何损坏,则可以轻松完成此操作。(按你的 jsfiddle 上的 tab,你就会明白我的意思。) (2认同)

Tyl*_*uth 5

要扩展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;
}; 
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

这对用户来说更有意义,并允许JavaScript在每次选择任何选项(包括早期选项)时运行.

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


Pau*_*rge 5

首先,您使用 onChange 作为事件处理程序,然后使用标志变量使其在每次进行更改时执行您想要的功能

<select
Run Code Online (Sandbox Code Playgroud)

<select
Run Code Online (Sandbox Code Playgroud)
var list = document.getElementById("list");
var flag = true ; 
list.onchange = function () {
if(flag){
document.bgColor ="red";
flag = false;

}else{
document.bgColor ="green";
flag = true;
}
}
Run Code Online (Sandbox Code Playgroud)


dsi*_*gnr 5

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

我决定做一些简单的黑客比替代品onChange()使用并不真正意味着用于此目的的其他事件(blurclick,等)

我解决的方法:

只需预先添加一个占位符选项标签,例如对其没有价值的 select。

因此,而不是仅仅使用以下结构,这需要 hack-y 替代方案:

<select>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
Run Code Online (Sandbox Code Playgroud)

考虑使用这个:

<select>
  <option selected="selected">Select...</option>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
Run Code Online (Sandbox Code Playgroud)

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

在回答这个问题时,我正在编写一个复杂的 Vue 应用程序,我发现这个设计选择大大简化了我的代码。在我解决这个问题之前,我花了几个小时解决这个问题,而且我没有重新编写很多代码。但是,如果我使用 hacky 替代方案,我将需要考虑边缘情况,以防止 ajax 请求的双重触发等。这也不会混淆默认浏览器行为作为一个很好的奖励(在移动设备上测试)浏览器也一样)。

有时,您只需要退后一步,从全局考虑最简单的解决方案。