【问题标题】:Make knockout listen to values changes which are not a result of a keystroke [duplicate]让淘汰赛收听不是击键结果的值更改[重复]
【发布时间】:2016-08-17 21:56:14
【问题描述】:
self.totalHours = ko.pureComputed(function() {
        var start=self.num1;
        var end=self.num2;
        return start+end; 
});

<input   type="text" data-bind="textInput: start">
<input  type="text" data-bind="textInput: end">
<input  type="text" data-bind='text: totalHours()'>

上面的第一个是我的viewmodel 的一部分,第二个是我的model 的一部分。 num1,num2 是可观察的。每次我手动更改上述前两个输入中的值时,第三个输入会立即更新;但是,当值通过代码更改时,knockout 不会监听更改并且total 不会更新。如何让 Knockout 听从代码引发的变化?

【问题讨论】:

  • 你如何通过代码更改值,举个例子。如果您只是访问模型并更改那里的值...它不会让步,淘汰赛会在 applyBinding 上重新构建对象并使用它自己的结构。
  • 感谢 Roy J。这解决了我的问题!

标签: javascript knockout.js


【解决方案1】:

您可以在这里修复和改进很多东西:

  • 当在其方法中使用的可观察对象发生变化时,计算值将重新评估:self.num1 和/或self.num2 需要可观察和使用() 评估
  • 如果你想绑定&lt;input&gt;的值,你必须使用value或textInput数据绑定; text 绑定将不起作用。
  • 如果你想写入一个计算,你必须指定一个write 方法。您必须告诉淘汰赛如何更新计算的依赖项以确保所有值加起来。 (例如:设置totalHours 可以设置num1 到totalHours 和num2 到0)
  • 您已绑定到start 和end,而您的视图模型属性被命名为num1 和num2。
  • 使用value 或textInput 时,用户输入将作为字符串返回。如果您想在任何数学中使用它们,则需要将字符串解析为数字。

现在所有代码都应该可以正常工作了,您可以通过输入或代码更新视图模型的值:

var ViewModel = function() {
  var self = this;
  
  self.num1 = ko.observable(0);
  self.num2 = ko.observable(0);
  
  self.totalHours = ko.pureComputed(function() {
    var start = parseFloat(self.num1());
    var end = parseFloat(self.num2());
    return start + end;
  });
  
};

var vm = new ViewModel();

ko.applyBindings(vm);

// Updating your values from code:
vm.num1(1);
vm.num2(2);

// Whenever the values need to be updated via js,
// you should change the source values, _not_ the
// <input>'s values. Worst case scenario, you'll
// have to do something like this:

var updateNum1ViaDOM = function() {
  ko.dataFor(document.querySelector("input")).num1(5);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input type="text" data-bind="textInput: num1">
<input type="text" data-bind="textInput: num2">
<span data-bind='text: totalHours'></span>

注意:最好使用扩展器来强制 num1 和 num2 为数字:Live Example 1: Forcing input to be numeric

【讨论】:

  • 但是,你对我的问题只字未提!如果 num1 或 num2 被代码更改,则 span 内的文本不会自动更新。仅当我手动更改值时才会更新...
  • 修复错误时,从代码(例如:self.num1(12))或通过输入字段更新可观察对象之间应该没有区别。当你想改变值时,你应该改变 viewmodel 的属性,而不是改变 DOM 元素的属性。您如何“通过代码更改值”?
【解决方案2】:

不确定这是否是复制粘贴问题,但您发布的代码将无法按预期工作。我已经更新了示例,在更改可观察值时,必须将其作为参数传递,以免覆盖可观察到的淘汰

self.start = ko.observable();
self.end = ko.observable();

self.totalHours = ko.computed(function() {
    return self.start() + self.end();
});

<input   type="text" data-bind="textInput: start">
<input  type="text" data-bind="textInput: end">
<input  type="text" data-bind='text: totalHours()'>

//Then when changing the value by code
var newValue = 42;
model.start(newValue); //assuming you are making the change outside your viewmodel

*刚刚注意到,当您编辑绑定到 totalHours 的输入时,此代码将引发异常,因为它没有定义写入处理程序。这是一个单独的问题。

【讨论】:

    猜你喜欢
    • 2020-07-10
    • 2018-03-30
    • 2021-10-09
    • 2014-04-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-26
    • 2012-11-07
    • 1970-01-01
    相关资源
    最近更新 更多