更改 <select> 的选项并使用 JavaScript 触发事件

Posted

技术标签:

【中文标题】更改 <select> 的选项并使用 JavaScript 触发事件【英文标题】:Change <select>'s option and trigger events with JavaScript 【发布时间】:2013-10-20 05:34:56 【问题描述】:

如何使用 javascript(没有任何库如 jQuery)更改 html &lt;select&gt; 的选项,同时触发与用户进行更改相同的事件?

例如使用以下代码,如果我用鼠标更改选项,则会触发一个事件(即运行onchange)。但是,当我使用 JavaScript 更改选项时,它不会触发任何事件。当使用 JavaScript 选择一个选项时,是否可以触发触发关联的事件处理程序,如 onclickonchange 等?

<select id="sel" onchange='alert("changed")'>
  <option value='1'>One</option>
  <option value='2'>Two</option>
  <option value='3'>Three</option>
</select>
<input type="button" onclick='document.getElementById("sel").options[1].selected = true;' value="Change option to 2" />

http://jsfiddle.net/xwywvd1a/

【问题讨论】:

但是你想触发 onchange 事件吗?你可以在选择选项的地方做同样的事情.. 【参考方案1】:

很遗憾,您需要手动触发change 事件。而使用Event Constructor 将是最好的解决方案。

var select = document.querySelector('#sel'),
    input = document.querySelector('input[type="button"]');
select.addEventListener('change',function()
    alert('changed');
);
input.addEventListener('click',function()
    select.value = 2;
    select.dispatchEvent(new Event('change'));
);
<select id="sel" onchange='alert("changed")'>
  <option value='1'>One</option>
  <option value='2'>Two</option>
  <option value='3' selected>Three</option>
</select>
<input type="button" value="Change option to 2" />

当然,IE 不支持Event 构造函数。所以你可能需要用这个来填充:

function Event( event, params ) 
    params = params ||  bubbles: false, cancelable: false, detail: undefined ;
    var evt = document.createEvent( 'CustomEvent' );
    evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
    return evt;

【讨论】:

如果我再次选择相同的选项会怎样。它不会再次触发更改事件。 如果我运行 $('#sel').val('3');它不会着火。你知道为什么吗? 对于 React 开发者,你必须使用 new Event('input', bubbles: true )。气泡:true 对于将事件传播到 React 的事件处理层至关重要。【参考方案2】:

我的解决方案的小提琴是here。但是以防万一它过期,我也会粘贴代码。

HTML:

<select id="sel">
  <option value='1'>One</option>
  <option value='2'>Two</option>
  <option value='3'>Three</option>
</select>
<input type="button" id="button" value="Change option to 2" />

JS:

var sel = document.getElementById('sel'),
    button = document.getElementById('button');

button.addEventListener('click', function (e) 
    sel.options[1].selected = true;

    // firing the event properly according to ***
    // http://***.com/questions/2856513/how-can-i-trigger-an-onchange-event-manually
    if ("createEvent" in document) 
        var evt = document.createEvent("HTMLEvents");
        evt.initEvent("change", false, true);
        sel.dispatchEvent(evt);
    
    else 
        sel.fireEvent("onchange");
    
);

sel.addEventListener('change', function (e) 
    alert('changed');
);

【讨论】:

另外:button.addEventListener('click', function (e) sel.options[1].selected = true; /*since ie9 this is possible, for ie8 and below you need to add some hacks*/ sel.dispatchEvent( new CustomEvent('change') ); ); 感谢 Angular 中的 Karol“createEvent”路径也适用于 IE11 :-)【参考方案3】:

就这么简单:

var sel = document.getElementById('sel');
var button = document.getElementById('button');

button.addEventListener('click', function (e) 
    sel.options[1].selected = true;
    sel.onchange();
);

但是这种方式有问题。您不能像使用普通函数那样调用事件,因为可能有多个函数在监听一个事件,并且它们可以通过几种不同的方式进行设置。

不幸的是,触发事件的“正确方法”并不容易,因为您必须在 Internet Explorer(使用 document.createEventObject)和 Firefox(使用 document.createEvent("HTMLEvents"))中以不同的方式进行操作

var sel = document.getElementById('sel');
var button = document.getElementById('button');

button.addEventListener('click', function (e) 
    sel.options[1].selected = true;
    fireEvent(sel,'change');

);


function fireEvent(element,event)
    if (document.createEventObject)
    // dispatch for IE
    var evt = document.createEventObject();
    return element.fireEvent('on'+event,evt)
    
    else
    // dispatch for firefox + others
    var evt = document.createEvent("HTMLEvents");
    evt.initEvent(event, true, true ); // event type,bubbling,cancelable
    return !element.dispatchEvent(evt);
    

【讨论】:

在 react/electron 中遇到了这个问题。这个答案的最后一部分是唯一对我有用的解决方法!谢谢。【参考方案4】:

试试这个:

<select id="sel">
 <option value='1'>One</option>
  <option value='2'>Two</option> 
  <option value='3'>Three</option> 
  </select> 


  <input type="button" value="Change option to 2"  onclick="changeOpt()"/>

  <script>

  function changeOpt()
  document.getElementById("sel").options[1].selected = true;

alert("changed")
  

  </script>

【讨论】:

【参考方案5】:

整个创建和调度事件都有效,但是由于您使用的是onchange 属性,您的生活可以简单一点:

http://jsfiddle.net/xwywvd1a/3/

var selEl = document.getElementById("sel");
selEl.options[1].selected = true;
selEl.onchange();

如果您使用浏览器的事件 API(addEventListener、IE 的 AttachEvent 等),那么您将需要像其他人已经指出的那样创建和调度事件。

【讨论】:

【参考方案6】:

这些问题可能与您的要求有关:

How can I trigger an onchange event manually?

How to trigger an event in an input field changed with javascript

以下是我的想法:您可以像这样在 onclick 事件中叠加多个调用:

<select id="sel" onchange='alert("changed")'>
  <option value='1'>One</option>
  <option value='2'>Two</option>
  <option value='3'>Three</option>
</select>
<input type="button" onclick='document.getElementById("sel").options[1].selected = true; alert("changed");' value="Change option to 2" />

您也可以调用一个函数来执行此操作。

如果你真的想调用一个函数并且两者的行为方式相同,我认为这样的事情应该可以工作。它并没有真正遵循“函数应该做一件事并做好”的最佳实践,但它确实允许您调用一个函数来处理更改下拉列表的两种方式。基本上,我在 onchange 事件上传递 (value),在 onclick 事件上传递 (null, index of option)。

这里是代码笔:http://codepen.io/mmaynar1/pen/ZYJaaj

<select id="sel" onchange='doThisOnChange(this.value)'>
<option value='1'>One</option>
<option value='2'>Two</option>
<option value='3'>Three</option>
</select>
<input type="button" onclick='doThisOnChange(null,1);' value="Change option to 2"/>

<script>
doThisOnChange = function( value, optionIndex)

    if ( optionIndex != null )
    
       var option = document.getElementById( "sel" ).options[optionIndex];
       option.selected = true;
       value = option.value;
    
    alert( "Do something with the value: " + value );

</script>

【讨论】:

这是另一个虚假的解决方案。如果有人在select 元素上为onchange 附加了很多处理程序怎么办?这座建筑将如何运作?可以肯定的一件事是它不会触发它们中的任何一个......【参考方案7】:

使用 Razor 的 HTML:

 @Html.DropDownList("test1", Model.SelectOptionList, new  id = "test1", onchange = "myFunction()" )

JS代码:

function myFunction() 

            var value = document.getElementById('test1').value;

            console.log("it has been changed! to " + value );
        

【讨论】:

【参考方案8】:

您可以在更改 onclick 事件的选定选项后手动触发事件:document.getElementById("sel").onchange();

【讨论】:

只有在设置了onchange 属性时才有效(有一些限制),不适用于内联处理程序。 document.getElementById(...).onchange 如果没有内联处理程序,则不是函数。

以上是关于更改 <select> 的选项并使用 JavaScript 触发事件的主要内容,如果未能解决你的问题,请参考以下文章

Vue:如何根据选择的选项更改路线,并在 <select> 元素中显示默认选择的选项?

Bootstrap 3 <select> 将下拉箭头向左移动并更改其块的颜色

ajax异步提交数据动态更改select选项

如何使用 ajax 更改所选选项 [关闭]

在悬停时更改选择列表选项背景颜色

Laravel Livewire:在选择输入的更改上传递选项值