KnockoutJS 选项与重复值绑定
我正在使用 Knockout.js 构建一个简单的应用程序作为概念证明。由于我对 Knockout 非常陌生,所以这个问题中的代码可能远非完美,并且表现出不好的做法,所以请随时告诉我是否是这种情况!
我正在使用 options
绑定来生成以下内容一个 select
元素:
<select data-bind="options: titles, optionsText: 'display', optionsValue: 'value'">
</select>
视图模型看起来像这样:
var ViewModel = function() {
this.titles = ko.observableArray([]);
};
在 DOM 准备就绪时,我将一些值推送到该可观察数组中(每个值都是一个对象文字,代表一个“标题”,例如“先生”,“夫人”等):
var data = [
{ value: "Mr", display: "Default Value" },
{ value: "Miss", display: "Miss" },
{ value: "Mr", display: "Mr" },
{ value: "Ms", display: "Ms" }
];
ko.applyBindings(view);
for(var i = 0; i < data.length; i++) {
view.titles.push(data[i]); //Push titles into observable array
}
别问为什么有两个对象的值为“Mr”,这就是我必须处理的数据的方式。我无法改变它。然而,这就是导致问题的原因。我希望第一个对象代表所选选项,但事实并非如此。第三个对象代表实际上最终成为默认选择的 option
元素。
我相信这是因为可观察数组导致 option
元素在循环迭代时被逐一添加到 DOM 中。 Knockout 尝试通过检查其值来保留所选选项。第一次迭代后,所选选项
的值为“Mr”。第三次迭代后,出现另一个值为“Mr”的 option
,因此 Knockout 认为它是之前选择的选项并选择它。
这是演示该问题的小提琴链接。应选择“默认值”选项,但没有选择。如果您单击该按钮再次添加具有相同值的另一个选项,该选项就会被选中,但根据文档,它不应该被选中。
我的问题是,如何防止这种行为?
I'm building a simple app with Knockout.js as a proof of concept. As I'm very new to Knockout, the code in this question may be far from perfect and exhibit bad practices, so feel free to let me know if that's the case!
I'm using the options
binding to produce the contents of a select
element:
<select data-bind="options: titles, optionsText: 'display', optionsValue: 'value'">
</select>
The View Model looks like this:
var ViewModel = function() {
this.titles = ko.observableArray([]);
};
On DOM ready I am pushing some values into that observable array (each value is an object literal, representing a "title", e.g. "Mr", "Mrs" etc):
var data = [
{ value: "Mr", display: "Default Value" },
{ value: "Miss", display: "Miss" },
{ value: "Mr", display: "Mr" },
{ value: "Ms", display: "Ms" }
];
ko.applyBindings(view);
for(var i = 0; i < data.length; i++) {
view.titles.push(data[i]); //Push titles into observable array
}
Don't ask why there are two objects with the value "Mr", that's just the way the data I have to deal with comes. I can't change it. However, this is what causes the problem. I would expect the first object to represent the selected option, but that's not the case. The third object represents the option
element that actually ends up as the default selection.
I believe this is due to the fact that the observable array causes the option
elements to be added to the DOM one by one as the loop iterates. Knockout attempts to preserve the selected option by checking it's value. After the first iteration, the selected option
has the value "Mr". After the third iteration there is another option
with the value "Mr" so Knockout thinks that it was the previously selected option and selects it.
Here's a link to a fiddle demonstrating the problem. The "Default Value" option should be selected, but is not. If you click the button to add another option with the same value again, that becomes selected, but, according to the documentation, it should not.
My question is, how can this behaviour be prevented?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为什么要将项目一项一项推入数组?你可以这样做:
而不是
这也可以解决你的问题 - 默认情况下会选择第一项。另外,如果您不打算向该数组添加新项目,您可以使用 ko.observable 而不是 ko.observableArray
UPDATE:
Knockoutjs 似乎不喜欢具有相同值的多个选项。如果您将值绑定添加到选择标记(它将选择第三项,而不是第一项),我的代码将无法正常工作。但是,由于 knockoutjs 允许您访问选定的对象(通过值绑定),因此您可以删除 optionsValue 绑定并通过值绑定访问值:jsfiddle.net/ej9Ue/1
Why are you pushing items into array one by one? You could just do:
instead of
This would also fix your problem - the first item would be selected by default. Also, if you are not planning on adding new items to that array, you could use ko.observable instead of ko.observableArray
UPDATE:
Knockoutjs doesn't seem to like multiple options with the same value. My code won't work properly if you add value binding to a select tag (it will select third item, not first). However, since knockoutjs allows you to access selected object (via value binding), you can remove optionsValue binding and access value via value binding: jsfiddle.net/ej9Ue/1