注意:这个问题与 Knockout.js 无关,而是关于元素的selectedOptions
属性。<select>
这是参考:
我认为这对 Javascript 开发人员来说是一个不错的功能。支持非常有限,但无论如何它都在增长。Chrome、Opera 和 Safari 应该已经支持它。
问题是我无法弄清楚它是如何工作的。该行为应该非常简单,产生所选选项的实时集合,但事实并非如此。您会想象selectedOptions
每次用户选择一个选项时都会发生变化,对吧?错误的。我准备了一个测试用例:
在这个例子中,Opera 11.64总是返回第一个选择的值,不管你之后做什么,而 Chrome 21 dev 和 19 stable 有一个奇怪的行为。执行以下步骤:
- 选择“一个”。正如预期的那样,在输出和控制台中,您都会得到“一”。
- 使用 Ctrl 也选择“两个”。在控制台中你得到“一,二”,在输出中它仍然是“一”。
- 也选择“三”。在控制台中是“一,二,三”,在输出中是“一,二”。
- 现在只选择“两个”。在控制台中,您在输出中获得“Two”,“Two,”(注意两个逗号)。
但是,如果您注释掉该console.log
行,您总是会得到正确的输出。如果交换两条指令,或者将值存储在单独的字符串中,则可以在控制台和输出中获得预期的行为,如下所示:
那么,我错过了什么selectedOptions
吗?依赖这个可能有错误实现的属性是否为时过早?是console.log
在 Chrome 中创建问题吗?s有什么我不知道HTMLCollection
的吗?
我没有安装 Safari,有人可以检查它的行为吗?
2013 年 2 月 18 日更新:我不知道什么时候发生了变化,但 Chrome 24.0.1312.57 和 Opera 12.14 现在似乎都可以正常工作。Firefox 18.0.2 和 Internet Explorer 10 仍然必须实现该属性。
2013 年 9 月 17 日更新: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,它只返回 aArray
而不是 a NodeList
。
28/5/2014 更新:看起来 FirefoxselectedOptions
从 r25 开始实施。