读入可计算的淘汰赛并不总是用扩展器射击
read in knockout computable not always firing with extender
这可能最容易用 fiddle http://jsfiddle.net/LkqTU/32190/
来描述
我有一个名为 price 的可观察对象,它有一个扩展符,因此它四舍五入到两位数并且不允许非数字。
我有一个可写的计算可观察对象,它前面有一个美元符号。
但是,如果扩展器 returns 0. 第二次发生 $0 不会返回到文本框(计算的可观察值),所以如果我在文本框(计算的可观察值)中键入 hello world,价格会正确报告0,格式化后的价格显示为 0 美元。但是,如果我清除它并再次输入 hello world 。这次价格仍然是 0 美元,但格式化价格文本框显示的是 hello world(即使格式化价格报告为 0 美元)。一定是某处遗漏了通知?
这是代码。
ko.extenders.numeric = function(target, precision) {
//create a writable computed observable to intercept writes to our observable
var result = ko.pureComputed({
read: target, //always return the original observables value
write: function(newValue) {
var current = target(),
roundingMultiplier = Math.pow(10, precision),
newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue),
valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;
//only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
}
}).extend({
notify: 'always'
});
//initialize with current value to make sure it is rounded appropriately
result(target());
//return the new computed observable
return result;
};
function model() {
var self = this;
this.price = ko.observable('29.01').extend({
numeric: '2'
});
this.formattedPrice = ko.computed({
read: function() {
return '$' + this.price()
},
write: function(value) {
value = parseFloat(value.replace(/[^\.\d]/g, ""));
this.price(isNaN(value) ? 0 : value);
},
owner: this
});
}
var mymodel = new model();
$(document).ready(function() {
ko.applyBindings(mymodel);
});
似乎对我有用的是扩展 formattedPrice
计算变量以始终通知和修改 write 方法以仅传递值而不是检查 isNaN;你的扩展器无论如何都会这样做并强制一个 0 使你的 if (newValue !== current)
测试永远不会 returns 为真,因为在这种情况下 newValue 和 current 将始终为 0(NaN !== 0 will 通过检查):
this.formattedPrice = ko.computed({
read: function() {
return '$' + this.price()
},
write: function(value) {
value = parseFloat(value.replace(/[^\.\d]/g, ""));
this.price(value); //just pass in nan or the value so the extender can check/notify if newValue !== current
},
owner: this
}).extend({
notify: 'always'
});
已更新 fiddle:http://jsfiddle.net/LkqTU/32192/
这可能最容易用 fiddle http://jsfiddle.net/LkqTU/32190/
来描述我有一个名为 price 的可观察对象,它有一个扩展符,因此它四舍五入到两位数并且不允许非数字。
我有一个可写的计算可观察对象,它前面有一个美元符号。
但是,如果扩展器 returns 0. 第二次发生 $0 不会返回到文本框(计算的可观察值),所以如果我在文本框(计算的可观察值)中键入 hello world,价格会正确报告0,格式化后的价格显示为 0 美元。但是,如果我清除它并再次输入 hello world 。这次价格仍然是 0 美元,但格式化价格文本框显示的是 hello world(即使格式化价格报告为 0 美元)。一定是某处遗漏了通知?
这是代码。
ko.extenders.numeric = function(target, precision) {
//create a writable computed observable to intercept writes to our observable
var result = ko.pureComputed({
read: target, //always return the original observables value
write: function(newValue) {
var current = target(),
roundingMultiplier = Math.pow(10, precision),
newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue),
valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;
//only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
}
}).extend({
notify: 'always'
});
//initialize with current value to make sure it is rounded appropriately
result(target());
//return the new computed observable
return result;
};
function model() {
var self = this;
this.price = ko.observable('29.01').extend({
numeric: '2'
});
this.formattedPrice = ko.computed({
read: function() {
return '$' + this.price()
},
write: function(value) {
value = parseFloat(value.replace(/[^\.\d]/g, ""));
this.price(isNaN(value) ? 0 : value);
},
owner: this
});
}
var mymodel = new model();
$(document).ready(function() {
ko.applyBindings(mymodel);
});
似乎对我有用的是扩展 formattedPrice
计算变量以始终通知和修改 write 方法以仅传递值而不是检查 isNaN;你的扩展器无论如何都会这样做并强制一个 0 使你的 if (newValue !== current)
测试永远不会 returns 为真,因为在这种情况下 newValue 和 current 将始终为 0(NaN !== 0 will 通过检查):
this.formattedPrice = ko.computed({
read: function() {
return '$' + this.price()
},
write: function(value) {
value = parseFloat(value.replace(/[^\.\d]/g, ""));
this.price(value); //just pass in nan or the value so the extender can check/notify if newValue !== current
},
owner: this
}).extend({
notify: 'always'
});
已更新 fiddle:http://jsfiddle.net/LkqTU/32192/