更改 <option> 的 .html() 会将 <option> 的 selectedIndex 属性 从“-1”重置为“0”

Changing .html() of <option> resets selectedIndex property of <option> from '-1' to '0'

<select> 中更改 <option>.html() 时使用 jQuery(我之前将 selectedIndex 属性 设置为 -1) 将 <select>selectedIndex 属性 从“-1”重置为“0

<!DOCTYPE html>
<html>
<head>
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
<select id="myselect" class="drpmnu">

   <option id="one" >(01)</option>

   <option id="two" >(02)</option>

   <option id="three" >(03)</option>

</select>
  <script>
    $(".drpmnu").prop('selectedIndex', -1)
    $('#three').html("moo")
  </script>
</body>
</html>

http://jsbin.com/filowe/2/edit?html,output

因为你在预置索引后设置了$('#three')的HTML内容。因此,如果您想保留 -1 的索引,请重新排列您的代码以按顺序加载。

<script>
    $('#three').html("moo");
    $(".drpmnu").prop('selectedIndex', -1);
</script>

当元素值改变时会自动触发onchange事件。因此,索引的重置。

不同浏览器的行为不同。我刚刚检查了 firefox,它没有任何错误。它向我显示了一个空的下拉列表,我检查了 selected 索引为 -1。但是 Chrome 中的结果不一样。

理想情况下,-1 用于 select 当没有选项是 select 启动时。我不确定是否可以在所有浏览器中以编程方式设置 -1。

Changing option's HTML does not trigger the change event, if it would - the following code will end up running infinite loop.

var i = 0;
$(".drpmnu").change(function (e) {
    i++;
    $('#three').html("data" + i);
})

起初我研究了 JQuery .html() function, but couldn't find anything that could cause the problem. Then I've tried to change innerHTML property without jquery(这是我应该首先做的)。它在 Firefox 33.1 和 34.0.5 上看起来不错,但重置 selectedIndex 为 Chrome 40.0.2214.94、IE 10 和 Opera 27.0.1689.66。

我认为这证明@Blake Plumb 的评论对于某些浏览器是正确的。

It is a repaint issue. When you change the text of the option is causes the select to repaint. In the repaint there is an issue where the prop gets reset to the default value.

这个案例在HTML5 spec中提到:

On setting, the selectedIndex attribute must set the selectedness of all the option elements in the list of options to false, and then the option element in the list of options whose index is the given new value, if any, must have its selectedness set to true and its dirtiness set to true.

Note: This can result in no element having a selectedness set to true even in the case of the select element having no multiple attribute and a display size of 1.

...

如果插入节点或删除节点导致选项列表获得或丢失一个或多个选项元素,或者如果选项列表中的选项元素asks for a reset,那么,如果select 元素的 multiple 属性不存在,select 元素的显示大小为 1,并且 select 元素的选项列表中没有选项元素具有 selectedness 设置为真,用户代理必须设置 selectedness 选项列表中第一个选项元素的 selectedness 未被禁用的树顺序选项, 为真。

通过设置 innerHTMLtextContent 属性 来更改选项会触发此重置(Firefox 除外),但 text 属性(这仅 <option>)不会触发它(IE 除外)。

// these triggers the <select> element's reset (except on Firefox)
$("#three")[0].innerHTML   = "foo";
$("#three")[0].textContent = "foo";

// this does not trigger the reset (except on IE)
$("#three")[0].text = "foo";

Firefox 更严格地遵循规范,它只会在有新的 <option> 或删除其中一个 <option> 时重置 <select>。但是在将 <option>selected 属性 设置为 false 期间它无法执行重置(但 that should trigger 重置也是如此)。

简而言之,当前所有浏览器都无法完全实现规范,因此唯一的跨平台解决方法是将 selectedIndex 更改为 select(及其后代)的最后一个操作元素):

$("#three").html("moo");
$(".drpmnu").prop("selectedIndex", -1);