在我的MVC应用程序中通过以下方式创建多个Dropdown:
<select data-bind="options: findGroup(1).items(),
optionsText: 'country',
optionsValue: 'id',
value: selectedItem(1),
event: { change: selectionChange }"></select>
findgroup(x)和selectedItem(x)是我的ViewModel中的全局函数,而所有下拉列表都是相同的。
selectedItem(x)应返回当前所选的下拉选项。 selectedItem(x)是一个返回计算出的挖掘可观察量的函数。
现在我面临的问题是,selectionChange事件被触发了两次。看一下这个小提琴的例子:http://jsfiddle.net/LGveR/20/ 在此示例中,如果更改“下拉”框的值,则可以看到selectionCahnge事件被触发两次。
当我保留值:selectedItem(x)out(因此代码中没有计算函数)时它不会:参见:http://jsfiddle.net/LGveR/21/
我认为第二次触发事件来自于计算函数selectedItem(x)中的可观察事实
grp.selectedItem(grp.findItemByValue(value));
已设置。 如何防止这个可观察的设置导致“改变”事件?
TIA, 保罗
HTML:
<select data-bind="options: findGroup(1).items(),
optionsText: 'country',
optionsValue: 'id',
value: selectedItem(1),
event: { change: selectionChange }"></select> <span data-bind="text: 'aantal: ' + findGroup(1).items().length"></span>
<br /> <span data-bind="text: 'Group Selected Country: ' + findGroup(1).selectedItem().country"></span>
<br /> <span data-bind="text: 'Computed Selected Country: ' + selectedItem(1)().country"></span>
<br /> <span data-bind="text: 'after select: ' + counter()"></span>
<br />
使用Javascript:
var group = function (id) {
this.id = id;
this.items = ko.observableArray() || {};
this.selectedItem = ko.observable();
this.addItem = function (data) {
this.items.push(data);
};
this.findItemByValue = function (id) {
return ko.utils.arrayFirst(this.items(), function (item) {
return item.id === id;
});
}
};
var grpItem = function (id, country) {
this.id = id;
this.country = country;
};
var ViewModel = function () {
this.groups = ko.observableArray() || {};
this.counter = ko.observable(0);
this.selectionChange = function (data, event, selector, item) {
this.counter(this.counter() + 1);
};
this.addGrp = function (data) {
this.groups.push(data);
};
this.findGroup = function (groupId) {
var ret = ko.utils.arrayFirst(this.groups(), function (c) {
return c.id === groupId;
});
return ret;
};
this.selectedItem = function (groupId) {
var grp = this.findGroup(groupId);
return ko.computed({
read: function () {
return this.findGroup(groupId).selectedItem();
},
write: function (value) {
grp.selectedItem(grp.findItemByValue(value));
}
}, this);
};
};
var vm = new ViewModel();
var p = new group(1);
var a = new grpItem(1, 'holland');
var b = new grpItem(2, 'germany');
var c = new grpItem(3, 'brasil');
p.addItem(a);
p.addItem(b);
p.addItem(c);
vm.addGrp(p);
ko.applyBindings(vm);
答案 0 :(得分:1)
你在代码中做了几件奇怪的事情,这导致计算机重新计算了很多次。基本上,你通过设置一个具有依赖于observable的函数的observable来设置计算值,该函数重新计算你的计算(或者像那样疯狂的东西,参见http://jsfiddle.net/LGveR/25/以查看读取和写入的次数是多少次)。您可以通过几种简单的方法简化并解决此问题:
从select data-bind中删除optionsValue。这将设置 可观察数组中整个项的值(而不是 只是id)。然后,您可以简化计算的写入功能。
<select data-bind="options: findGroup(1).items(),
optionsText: 'country',
value: selectedItem(1),
event: { change: selectionChange }"></select>
和
this.selectedItem = function (groupId) {
var grp = this.findGroup(groupId);
return ko.computed({
read: function () {
return grp.selectedItem();
},
write: function (value) {
grp.selectedItem(value);
}
}, this);
};
或者,您可以删除viewmodel上的selectedItem 完全,并删除optionsValue(如在#1中)。然后,您只需要具有以下html的组observable:
<select data-bind="options: findGroup(1).items(),
optionsText: 'country',
value: findGroup(1).selectedItem,
event: { change: selectionChange }"></select>
<span data-bind="text: 'aantal: ' + findGroup(1).items().length"></span>
<br />
<span data-bind="text: 'Group Selected Country: ' + findGroup(1).selectedItem().country"></span>
...