如果外部更改值,则无法检测到可观察到的变化 [英] Knockout observable change not detected if value changed externally
问题描述
我有一个绑定到ko.observableArray
的文本框的列表.
I have a list of text boxes bound to the ko.observableArray
.
我必须确保文本框的值不能为空,并且我使用jQuery通过将blur()
I have to make sure that text box values can't be blank, and I do it with jQuery by setting the value to 0 if it's blank on blur()
问题在于使用jQuery完成的值更改未通过淘汰赛进行注册.
The problem is that the value change done with jQuery is not registered by knockout.
如何观察模型中的值变化?
请参阅我的简化提琴,以阐明要点- http://jsfiddle.net/k45gd/1/
See my simplified fiddle to get the point across - http://jsfiddle.net/k45gd/1/
HTML
<input type="number" data-bind="value: age" />
<span data-bind="text: age"></span>
<button data-bind="click: setAgeExternally">I want the label to change to 0</button>
JS
var model = function() {
this.age = ko.observable(21);
//this code is outside of the model, this is oversimplification
this.setAgeExternally = function(){
$('input').val(0);
}
};
ko.applyBindings(new model());
推荐答案
在您提供的示例中,您正在使用以下代码更新输入框:
In the example you provide, you're updating the input box with this code:
this.setAgeExternally = function(){
$('input').val(0);
}
考虑到输入绑定到age属性,这样做会更简单:
Considering that the input is bound to the age property, it would be simpler to do this:
this.setAgeExternally = function(){
this.age(0);
}
但是,由于age属性在您的视图模型中公开,因此即使实际上也不需要这样做.因此,外部代码可以做到这一点,并且实际上不需要setAgeExternally方法:
However, even that isn't really needed, as the age property is exposed on your viewmodel. So external code could just do this, and the setAgeExternally method isn't really needed:
model.age(0);
让我们回到您最初的问题-您所描述的问题,但不要为之发布代码.您提到您有绑定到可观察数组的输入框列表.
Let's jump back to your original problem - the one you describe but don't post code for. You mention that you have a list of input boxes bound to an observable array.
使用可观察数组时,您需要了解一个有趣的陷阱:
There is an interesting gotcha you need to be aware of when working with an observable array:
摘自 http://knockoutjs.com/documentation/observableArrays.html 上的文档:
关键点:observableArray跟踪数组中的对象, 不是这些对象的状态
Key point: An observableArray tracks which objects are in the array, not the state of those objects
仅将对象放入observableArray并不能完全 该对象的属性本身是可观察的.当然可以 如果您愿意,可以使这些属性可观察,但这是一个 独立选择.一个observableArray只是跟踪它的对象 保留,并在添加或删除对象时通知侦听器.
Simply 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 added or removed.
鉴于您列出的要求,根本不需要jQuery.您可以尝试以下三部分解决方案:
Given the requirements you list, there isn't any need for jQuery at all. You can try this three-part solution:
-
使您的observableArray包含可观察对象.因此,您最终会遇到类似这样的情况:
Make your observableArray contain observables. So you'd end up with something like:
var model = function() {
this.ages = ko.observableArray([
{age: ko.observable(13)},
{age: ko.observable(18)},
{age: ko.observable(16)},
{age: ko.observable(13)}
]);
};
接下来,创建一个敲除扩展器,如果空白,则将自动重置为0
Next, create a knockout extender that resets to 0 automatically if blank
ko.extenders.defaultIfBlank = function(target, defaultValue) {
var result = ko.computed({
read: target, //always return the original observables value
write: function(newValue) {
if (newValue == "") {
target(defaultValue);
} else {
target(newValue);
}
}
});
//initialize with current value to make sure it is not blank
result(target());
//return the new computed observable
return result;
};
将扩展器应用于数组中的可观察对象
Apply the extender to the observables in your array
var model = function() {
this.ages = ko.observableArray([
ko.observable(13).extend({defaultIfBlank: "0"}),
ko.observable(18).extend({defaultIfBlank: "0"}),
ko.observable(16).extend({defaultIfBlank: "0"}),
ko.observable(13).extend({defaultIfBlank: "0"})
]);
};
正在工作的小提琴: http://jsfiddle.net/tlarson/GF3Xe/
这篇关于如果外部更改值,则无法检测到可观察到的变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!