如果外部更改值,则无法检测到可观察到的变化 [英] Knockout observable change not detected if value changed externally

查看:65
本文介绍了如果外部更改值,则无法检测到可观察到的变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个绑定到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:

  1. 使您的observableArray包含可观察对象.因此,您最终会遇到类似这样的情况:

  1. 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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆