已选择选项已损坏或.

Is selectedOptions broken or...?

本文关键字:已损坏 选项 选择      更新时间:2023-09-26

注意:这个问题与Knockout.js无关,而是关于<select>元素的selectedOptions属性。这是参考:

http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#dom-select-selectedoptions

我认为这对Javascript开发人员来说是一个很好的功能。支持非常有限,但无论如何都在增长。Chrome,Opera和Safari应该已经支持它。

问题是我无法弄清楚它是如何工作的。该行为应该非常简单,生成所选选项的实时集合,但事实证明并非如此。你可以想象每次用户选择一个选项时selectedOptions都会改变,对吧?错。我准备了一个测试用例:

http://jsfiddle.net/f39cC/5/

在此示例中,无论您之后执行什么操作,Opera 11.64 始终返回选择的第一个值,而 Chrome 21 dev 和 19 stable 的行为很奇怪。执行以下步骤:

  1. 选择"一"。正如预期的那样,在输出和控制台中,您都会得到"一"。
  2. 也使用Ctrl选择"两个"。在控制台中,您得到"一,二",在输出中它仍然是"一"。
  3. 也选择"三个"。在控制台中它是"一,二,三",在输出中它是"一,二"。
  4. 现在仅选择"两个"。在控制台中,您可以得到"Two",在输出"Two,"(注意两个逗号)。

但是,如果您注释掉console.log行,则始终会得到正确的输出。如果交换两个指令,或者将值存储在单独的字符串中,则可以在控制台和输出中获得预期的行为,如下所示:

http://jsfiddle.net/f39cC/2/

那么,我错过了selectedOptions一些东西吗?现在依赖这个可能有错误实现的属性是否还为时过早?console.log是在 Chrome 中制造问题吗?关于HTMLCollection

有什么我不知道的吗?

我没有安装 Safari,有人可以检查它的行为吗?

更新 18/2/2013: 我不知道什么时候事情发生了变化,但 Chrome 24.0.1312.57 和 Opera 12.14 现在似乎都可以正常工作。Firefox 18.0.2 和 Internet Explorer 10 仍然需要实现该属性。

更新 17/9/2013: Firefox 24 和 IE 11 预览版仍然必须支持该属性。这是Firefox和IE8-11的简单解决方法:

Object.defineProperty(HTMLSelectElement.prototype, "selectedOptions", {
    get: (function() {
        try {
            document.querySelector(":checked");
            return function() {
                return this.querySelectorAll(":checked");
            };
        } catch (e) {
            return function() {
                if (!this.multiple) {
                    return this.selectedIndex >= 0
                            ? [this.options[this.selectedIndex]] : [];
                }
                for (var i = 0, a = []; i < this.options.length; i++)
                    if (this.options[i].selected) a.push(this.options[i]);
                return a;
            };
        }
    })()
});

对于IE8,它只返回一个Array而不是一个NodeList

更新 28/5/2014:看起来 Firefox 从 r25 开始实施selectedOptions

这个问题似乎比一个简单的错误更深一些。WebKit和Presto都未能正确支持selectedOptions这一事实为我们提供了暗示,即这取决于该属性应该是HTMLCollection的事实。

现在,HTMLCollection有其实时行为,因为当 DOM 发生某些事情(类的更改、节点的删除等)时,渲染引擎会使它们失效。但是选项的selected属性不会触发集合的失效,从而使其完全不可靠。

我想这里的问题是制作一种新的方式来使实时集合失效,这可能不是很简单,因为它可能会影响 DOM 的整个解释和处理方式。

目前,Chrome 21.0.1180.4 已删除该属性。