计算敲除的循环依赖性
Circular dependency of knockout computed
请参阅工作jsFiddle:http://jsfiddle.net/ruslans/vFK82/
我有3个字段:净价(不含税(、税额和总价(价格不含增值税+税额(。NetPrice和Total是可写的,即您可以更改它们中的任何一个,并且其他两个值必须自动计算。
我做这件事的方式是使用3个可观察到的和2个计算出的淘汰对象,但我想也许一个更了解淘汰的人可以提出一种更有效的方法来实现这一点。
html:
Net Price:
<input type="textbox" data-bind="value: NetPriceCalc" />
<br />Tax Amount:
<label data-bind="html: TaxAmt"></label>
<br />Total:
<input type="textbox" data-bind="value: TotalCalc" />
脚本:
var viewModel = {
NetPrice: ko.observable(100),
TaxAmt: ko.observable(20),
Total: ko.observable(120),
TaxRate: 0.2
};
viewModel.updateTaxAmt = function (useNetPrice) {
if (useNetPrice) {
return this.TaxAmt(this.NetPrice() * this.TaxRate);
} else {
var total = Number(this.Total());
var taxAmt = total - total / (1 + this.TaxRate);
return this.TaxAmt(taxAmt);
}
};
viewModel.updateNetPrice = function () {
this.NetPrice(Number(this.Total()) - Number(this.TaxAmt()));
};
viewModel.updateTotal = function () {
this.Total(Number(this.NetPrice()) + Number(this.TaxAmt()));
};
viewModel.NetPriceCalc = ko.computed({
read: function () {
console.log("NetPriceCalc read");
return viewModel.NetPrice();
},
write: function (value) {
console.log("NetPriceCalc write");
viewModel.NetPrice(value);
viewModel.updateTaxAmt(true);
return viewModel.updateTotal();
}
});
viewModel.TotalCalc = ko.computed({
read: function () {
console.log("TotalCalc read");
return viewModel.Total();
},
write: function (value) {
console.log("TotalCalc write");
viewModel.Total(value);
viewModel.updateTaxAmt(false);
return viewModel.updateNetPrice();
}
});
ko.applyBindings(viewModel);
对OP:的一些评论
ko.computed
的write
方法中不需要return
子句- 您的方法在多个地方使用
Number()
函数,您可能希望更改它以获得特定的精度(或用于验证用户输入的某个集中位置(。所以你可以使用ko.extenders来改进它。我特别推荐ko团队已经制作的名为ko.extenders.numeric
的扩展器 - 您的方法还在多个地方使用
console.log()
,您可能需要使用ko团队ko.extenders.logChange
制作的另一个ko.extender - 在这种情况下,我认为最好使用
subscribe
,而不是ko.computed
,因为它将占用更少的代码(而且可能不会更快(
我的方法是:
function viewModel() {
this.TaxRate = 0.2;
this.NetPrice = ko.observable().extend({ numeric: 2, logChange: "NetPrice" });
this.TaxAmt = ko.observable().extend({ numeric: 2, logChange: "TaxAmt" });
this.Total = ko.observable().extend({ numeric: 2, logChange: "Total" });
this.NetPrice.subscribe(function (newNetPrice) {
this.TaxAmt(newNetPrice * this.TaxRate);
this.Total(newNetPrice + this.TaxAmt());
}, this);
this.Total.subscribe(function (newTotal) {
this.TaxAmt(newTotal - newTotal / (1 + this.TaxRate));
this.NetPrice(newTotal - this.TaxAmt());
}, this);
this.NetPrice(100);
}
// then I have the extenders code copied exactly as seen in: http://knockoutjs.com/documentation/extenders.html)
ko.extenders.numeric = ...
ko.extenders.logChange = ...
// and finally init everything as usual
ko.applyBindings(new viewModel());
你可以在这里看到正在工作的小提琴:http://jsfiddle.net/protron/JFPgu/2/
请注意,此解决方案中的数字的小数位数永远不会超过数字扩展器上指定的小数位数(即使用户输入的值也会自动固定为所需的精度(。
将我的答案与gaurav目前接受的答案进行比较(这也是非常好和简单的(:我认为我的方法的主要优点是它可以让你使用这些很棒的扩展器。
一个稍微好一点且有效的方法可能是:
工作Fiddle
Html
Net Price:
<input type="textbox" data-bind="value: NetPrice" />
<br />Tax Amount:
<label data-bind="html: TaxAmt"></label>
<br />Total:
<input type="textbox" data-bind="value: Total" />
JS
function viewModel() {
var self = this;
self.NetPrice = ko.observable(100);
self.TaxRate = 0.2;
self.TaxAmt = ko.computed(function() {
return parseFloat(self.NetPrice()) * self.TaxRate;
});
self.Total = ko.computed({
read: function() {
return parseFloat(self.NetPrice()) + self.TaxAmt();
},
write: function(val){
var total = parseFloat(val);
var taxAmt = total - total / (1 + self.TaxRate);
self.NetPrice(total - taxAmt);
}
});
}
希望它能有所帮助!
不能保证这会解决问题,但有时启用延迟更新可以解决这样的问题。
这是一个值得注意的好功能,但在为已经运行的应用程序启用它时要小心——而且如果你确实有潜在的问题,那么你仍然需要修复它。
http://knockoutjs.com/documentation/deferred-updates.html
相关文章:
- jQuery:循环一个具有不同超时值的循环
- 在循环中分配json值时,值被覆盖
- 如何在下面的ES6循环中获得前面的文本
- 为什么“;未定义的“;在JavaScript中结束循环
- Javascript循环不会自我更新
- 如何使用jquery处理php循环通过元素
- 而循环只设置php中输入字段中的第一个值
- 循环遍历数组中的特定索引
- Javascript返回值只在循环中返回一次
- 按照选项卡索引的顺序循环一个jQuery选择
- 循环遍历以数组为值的Javascript对象
- 为什么JavaScript在for循环为3时向所有4发出警报
- 另一个ajax调用中的Jquery ajax调用在for循环中没有按预期工作
- 循环结束/推送到数组之前在页面上呈现EJS
- 循环比赛位置算法
- jQuery循环在特定位置暂停
- 我的javascript for循环不起作用
- 循环浏览多个身体背景图像
- Bookshelf注册表插件和节点循环依赖性错误
- 计算敲除的循环依赖性