javascript 淘汰赛。如何计算可观察数组内更改的数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12679215/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Knockoutjs. How to compute data changed inside observable array
提问by vkim
Please, look at my text. I try to use observableArray of knockoutjs and foreach to compute data of array. Example 1 works fine: total sum computed if you change data in the fields. But Example 2 is not working.
请看我的文字。我尝试使用knockoutjs 的observableArray 和foreach 来计算数组的数据。示例 1 工作正常:如果更改字段中的数据,则计算总和。但是示例 2 不起作用。
<html>
<head>
<title></title>
<script type='text/javascript' src='/js/jquery-1.8.2.min.js'></script>
<script type='text/javascript' src='/js/knockout-2.1.0.debug.js'></script>
</head>
<body>
<p>Example 1</p>
<div>
<p>
<input data-bind="value: fnum1" />
<input data-bind="value: fnum2" />
<span data-bind="text: ftotsum"></span>
</p>
</div>
<p>Example 2</p>
<div>
<p>
<!-- ko foreach: fields -->
<input data-bind="value: $data" />
<!-- /ko -->
<span data-bind="text: ltotsum"></span>
</p>
</div>
</body>
<script>
function vm(){
//Calc Example 1
var self = this;
self.fnum1 = ko.observable(1);
self.fnum2 = ko.observable(2);
self.ftotsum = ko.computed(function(){
return parseFloat(self.fnum1()) + parseFloat(self.fnum2());
});
//Calc Example 2
self.fields = ko.observableArray([1, 2]);
self.ltotsum = ko.computed(function(){
var total = 0;
ko.utils.arrayForEach(self.fields(), function(item) {
total += parseFloat(item);
})
return total;
});
};
ko.applyBindings(new vm());
</script>
</html>
采纳答案by Rynan
EDIT:Got fiddle working, Raffaele is correct in saying you need to wrap the observable inside an object, but you can do it within the array creation itself and I like to use the ko.utils to unwrap my observables, it does the same thing for observables but it won't crash if there is a non-observable passed to it. See fiddlefor full example.
编辑:小提琴工作,Raffaele 说你需要将 observable 包装在一个对象中是正确的,但是你可以在数组创建本身中完成它,我喜欢使用 ko.utils 来解开我的 observables,它做同样的事情对于 observables 但如果有一个不可观察的传递给它,它不会崩溃。有关完整示例,请参阅小提琴。
An observableArray doesn't make the values passed observable, this is a common mistake. An observableArray just observes the modifications to the array and not the values. If you want to have your values inside your array be observable you have to make them so.
observableArray 不会使传递的值成为可观察的,这是一个常见的错误。observableArray 只观察对数组的修改,而不是值。如果你想让你的数组中的值是可观察的,你必须让它们如此。
function vm(){
//Calc Example 1
var self = this;
self.fnum1 = ko.observable(1);
self.fnum2 = ko.observable(2);
self.ftotsum = ko.computed(function(){
return parseFloat(self.fnum1()) + parseFloat(self.fnum2());
});
//Calc Example 2
self.fields = ko.observableArray([{"num":ko.observable(1)},{"num":ko.observable(2)}]);
self.ltotsum = ko.computed(function(){
var total = 0;
ko.utils.arrayForEach(self.fields(), function(item) {
total += parseFloat(ko.utils.unwrapObservable(item.num));
});
return total;
});
};
ko.applyBindings(new vm());
Should work with the example above now.
现在应该使用上面的示例。
回答by Raffaele
The documentationsays:
该文件说:
Key point: An
observableArray
tracks which objects are in the array, not the state of those objectsSimply putting an object into an observableArray doesn't make all of that object's properties themselves observable. Of course, you can make those properties observable if you wish, but that's an independent choice. An observableArray just tracks which objects it holds, and notifies listeners when objects are addedor removed.
关键点:
observableArray
跟踪哪些对象在数组中,而不是这些对象的状态简单地将一个对象放入 observableArray 并不能使该对象的所有属性本身都是可观察的。当然,如果您愿意,您可以使这些属性可观察,但这是一个独立的选择。observableArray 只跟踪它持有哪些对象,并在添加或 删除对象时通知侦听器。
Your second example doesn't work because the value of the input fields is not boundto the values in the array. That values in the array are used only once, in the foreach
binding, but when you type in the input boxes, nothing triggers KO.
您的第二个示例不起作用,因为输入字段的值未绑定到数组中的值。数组中的值仅在foreach
绑定中使用一次,但是当您在输入框中键入时,不会触发 KO。
Here is a working fiddlewith a solution implemented. I used a helper ObsNumber
这是一个解决方案的工作小提琴。我用了一个帮手ObsNumber
function vm(){
var self = this;
var ObsNumber = function(i) {
this.value = ko.observable(i);
}
self.fields = ko.observableArray([new ObsNumber(1) ,
new ObsNumber(2)]);
self.sum = ko.computed(function(){
var total = 0;
ko.utils.arrayForEach(self.fields(), function(item) {
total += parseFloat(item.value());
});
return total;
});
};
ko.applyBindings(new vm());
and the following markup
和以下标记
<div>
<p>
<!-- ko foreach: fields -->
<input data-bind="value: $data.value" />
<!-- /ko -->
<span data-bind="text: sum"></span>
</p>
</div>?