Knoredout PureComputed在重新创建时调用订阅者

时间:2016-09-03 01:06:24

标签: javascript knockout.js publish-subscribe observable knockout-3.0

我有一组包含数据的表单。当我单击一个集合(或行)时,它会使用该组数据填充表单。

对于每个集合,我有一个pureComputed对象,只要其中一个输入发生变化,它就会更新数据库。

这很好用,只是当我点击另一个集合时,pureComputed会调用更新。我希望这不会发生,因为我使用构造函数构建输入集,因此我基本上替换了所有的observable及其各自的pureComputed属性。

例如:

var Form = function (data) {
    var $this = this;
    $this.value1 = ko.observable(data.value1);
    $this.value2 = ko.observable(data.value2);
    $this.model = ko.pureComputed(function () {
        return {
            value1: $this.value1(),
            value2: $this.value2(),
        };
    }).extend({ updateModel: url }); 
};

//Inside some module
var self = this;
self.viewmodel = {};

var load = function (url) {
    $.ajax({
        url: url, //etc
    }).done(function (response) {
        self.viewmodel.form(new Form(response));
    });
};
load('www.myapi.com/1');

var onClick = function () {
    load('www.myapi.com/2');
};

此外,页面加载时不会调用更新。单击新行时为什么会调用它?

编辑:UpdateModel代码......

ko.extenders.updateModel = function (target, options) {
    var url = options;

    target.subscribe(function (model) {
        $.ajax({
            url: url,
        }).done(function (response) {
            /* not setting any observables */
        });
    };

    return target;
};

编辑2 :以上实际上是在我的代码中工作。我把罪魁祸首缩小到下拉列表的淘汰赛绑定。

每个表格的一部分是下拉列表。我使用knockout的内置绑定作为下拉列表,我包含一个占位符。如果下拉列表的值为null或0,则该值将调用子描述。如果它大于0则那么罚款。

1 个答案:

答案 0 :(得分:1)

我已经采用了您的代码并在此处创建了一个工作示例版本。除非更改值,否则它不会运行更新功能。换句话说,"点击"不会更新任何内容。



ko.extenders.updateModel = function (target, options) {
  var url = options;

  target.subscribe(function (foo) {
    console.log(url, foo);
  });

  return target;
};

var Form = function (data) {
  var $this = this;
  $this.value1 = ko.observable(data.value1);
  $this.value2 = ko.observable(data.value2);
  $this.model = ko.pureComputed(function () {
    return {
      value1: $this.value1(),
      value2: $this.value2(),
    };
  }).extend({ updateModel: data.url }); 
};

//Inside some module
var vm = {};
vm.viewmodel = {
  form: ko.observable()
};

var counter = 0;
var load = function (url) {
  url = url + (++counter);
  setTimeout(function () {
    vm.viewmodel.form(new Form({
      value1: "1"+counter,
      value2: "2"+counter,
      url: url
    }));
  }, 100);
};

load('www.myapi.com/');

vm.onClick = function () {
  load('www.myapi.com/');
};

ko.applyBindings(vm);

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<div data-bind="with: viewmodel.form">
  <input data-bind="value: value1">
  <input data-bind="value: value2">
</div>
<button type="button" data-bind="click: onClick">click</button>
&#13;
&#13;
&#13;