我对KO相对较新(2天前开始),并尝试了一些简单的例子。目前,我遇到了这段代码的问题。
<div id="idChangeStyle">
<span data-bind="style: { background: GetAge() < 18 ? 'red':'white'}">Enter Your Age:</span>
<input type="text" data-bind="value: GetAge"></input>
</div>
function ageViewModel() {
var self = this;
self.age = ko.observable(18);
self.GetAge = ko.computed({
read: function () {
return self.age();
},
write: function (value) {
value = parseInt(String(value).replace(/[^\d]/g, ""));
if (isNaN(value))
self.age(18);
else
self.age(value);
}
});
};
ko.applyBindings(new ageViewModel(), document.getElementById('idChangeStyle'));
基本上,应用程序只需输入一个(年龄)。我正在使用可写的计算observable来解析输入到INTEGER并在解析之后是否我正在尝试将年龄设置为其默认值 即18.我在html上有一个简单的逻辑,如果年龄低于18,我将跨度的背景改为红色。
在正常情况下,它工作正常,这是我遇到问题时: -
Case 1:
Current Input: 18 (initial case)
enter *4* then tab //works
enter *a* then tab //work (defaults to 18)
enter *a* then tab //doesn't work
case 2:
current input: 18
enter *a *then tab* //*doesn't work
我检查了淘汰赛的代码,看看在下面一段代码运行的情况下会发生什么: -
if(isNaN(value))
self.age(18);
..在以下行中: -
// Ignore writes if the value hasn't changed
if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {
_latestValue
和arguments[0]
都具有相同的值(18),所以它什么都不做。
由于年龄值没有变化,因此viewmodel属性和UI不同步。
这是因为我做错了吗?
答案 0 :(得分:2)
问题在于,如果为observable输入相同的值,则不会将其视为值的更改,也不会通知订阅者。如果您连续多次输入错误状态,18
将首先设置为年龄并再次设置,不会发生任何更改事件。
话虽如此,为了解决这个问题,您必须手动通知订阅者。你可以通过在observable上调用valueHasMutated()
来做到这一点。
self.GetAge = ko.computed({
read: function () {
return self.age();
},
write: function (value) {
value = parseInt(String(value).replace(/[^\d]/g, ""));
if (isNaN(value)) self.age(18);
else self.age(value);
self.age.valueHasMutated(); // notify subscribers
}
});
答案 1 :(得分:2)
当我使用淘汰赛3.0时,我也有同样的情况。但这些三人组并没有帮助我,因为现在只有当计算出的属性值发生变化时才会通知
我解决了问题: 1)仅使用通知:始终
function ageViewModel(data) {
//notify will should be always, because age is a primitive type
this.age = ko.observable(data.age).extend({notify: "always"});
this.GetAge = ko.computed({
read: function () {
// notify will should be always, because computed return values of a primitive type.
return this.age();
},
write: function (value) {
value = parseInt(String(value).replace(/[^\d]/g, ""));
if (isNaN(value)) {
this.age(18);
}
else this.age(value);
},
owner: this
}).extend({notify: "always"});
};
2)使用notify:always和knockout.mapping
function ageViewModel(data) {
ko.mapping.fromJS(data, {}, this);
//notify will should be always, because age is a primitive type
this.age = this.age.extend({notify: "always"});
this.GetAge = ko.computed({
read: function () {
// notify will should be always, because computed return values of a primitive type.
return this.age();
},
write: function (value) {
value = parseInt(String(value).replace(/[^\d]/g, ""));
if (isNaN(value)) {
this.age(18);
}
else this.age(value);
},
owner: this
}).extend({notify: "always"});
};
答案 2 :(得分:0)
解决此问题的一种简单方法是将年龄设置为0,然后再将其设置为默认值。
即,改为:
if(isNaN(value)) {
self.age(0);
self.age(18);
}
我不知道淘汰赛会被认为是“正确”的方式,但这可能就是我要做的。