【问题标题】:subscribe event getting called while setting value设置值时调用订阅事件
【发布时间】:2014-12-17 23:54:46
【问题描述】:

我的 html 中的选择列表绑定到可观察数组

 <select data-bind="options: myData, optionsText: 'Name', value: selectedId"></select>

当我加载我的页面时,我将值设置为 observable selectedId

但是当我设置值时,它会立即调用它的订阅事件

  selectedId.subscribe(function (row) {
      // some logic for retrieving data
  });

我不想在以编程方式设置值时调用订阅事件,而只想在用户从列表中选择某些内容时调用。

有可能吗?找不到任何好的例子。

更新1 我以这种方式将值设置为我的 observable selectedId

selectedId(ko.utils.arrayFirst(data(), function(item) {
                    return item.id=== 5;
}));

我认为因此它触发了订阅事件

【问题讨论】:

  • selectedId的值怎么设置?
  • But when i set value it immediately calls its subscribe event:当然可以。值改变了。在您设置初始值之前之后不连接订阅怎么样?
  • @MattBurland 我们该怎么做?
  • @haim770 我将其设置为 selectedId(somevalue)
  • 你把selectedId(somevalue)放在selectedID.subscribe(//...前面

标签: html knockout.js observable


【解决方案1】:

如果您在实际订阅之前设置了初始值,那么您不应该触发订阅事件。例如:

function ViewModel() {
  var self = this;

  self.selectedID = ko.observable();
  self.selectedID(10); // this won't fire the event because we haven't subscribed yet

  self.selectedID.subscribe(function(value) {
    alert("value changed by user");
  });
}

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input type="number" data-bind="value: selectedID" />

现在,如果您想解决一般情况,其中值可能稍后以编程方式更改,并且您不希望 subscribe 触发,您可能希望有一个标志,您可以使用它来简单地跳过处理subscribe 处理程序。比如:

function ViewModel() {
  var self = this;

  self.selectedID = ko.observable();
  self.selectedID(10); // this won't fire the event because we haven't subscribed yet

  var _skipNotification = false; // this tells us whether or not we should process subscribe

  // putting this logic in a function makes it easier if you have multiple places 
  // where you need to programmatically set the id.
  function setSelectedID(value) {
    _skipNotification = true;
    self.selectedID(value);
    _skipNotification = false;
  }

  self.selectedID.subscribe(function(value) {
    if (!_skipNotification) {
      alert("value changed by user");
    }
  });

  self.changeProgrammatically = function() {
    setSelectedID(1);
  };
}

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input type="number" data-bind="value: selectedID" />
<input type="button" data-bind="click: changeProgrammatically" value="change programmatically" />

这是您的fiddle,已修复为使用上述技术。局部变量_skipNotification 在视图模型中定义并在订阅事件中检查。那么鼠标点击调用的importData函数如下所示:

 this.importData = function () {
     skipNotification = true;
     self.selectedGroup(ko.utils.arrayFirst(self.availableGroups(), function (val) {
         //debugger;
         return val.GroupId == 8;
     }));
     skipNotification = false;

     console.log("Lets see if it hits me first");
 };

这将设置selectedGroup 而不会导致selectedGroup.subscribe 的主体执行。请注意,结果selectedGroupId 未设置,因此尽管在下拉列表中选择了某些内容,但您的一个跨度仍会显示You have chosen Nothing。我不确定这是否是你真正想要的,但这似乎很有误导性。特别是因为现在让它正确读取You have chosen Football Team 的唯一方法是先选择其他内容,然后重新选择Football Team

【讨论】:

  • @Happy:您的更新并没有带来丝毫不同。发布一些实际演示问题的代码
  • 看看这个小提琴jsfiddle.net/FjRxn/82小提琴有问题。得到未定义的错误。这就是我几乎在我的代码中所做的。我很确定当您单击小提琴中的 importData 按钮时,将调用订阅事件
  • @Happy:我已更新您的fiddle 以修复您未定义的错误。您从未分配过self。您的问题完全可以通过我的第二个解决方案来解决。我建议您编辑您的问题以包含您在小提琴中的内容,因为您最初的问题完全不清楚。您在构造视图模型时连接订阅处理程序,但直到稍后响应事件时才设置selectedGroup
猜你喜欢
  • 2017-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多