获取然后从Knockout ObservableArray中删除随机对象

时间:2018-05-14 20:33:37

标签: knockout.js

我正在尝试从可观察数组中抓取一个随机对象,然后从数组中删除该对象,以便不再抓取它。但是,似乎所有对象都被删除得太快而且不正确,所以我用完了对象。

https://jsfiddle.net/vwfp9L7s/

HTML:

<ul id="personList">
  <li data-bind="with: getPerson() ">
    <p data-bind="text: $data.name"></p>
  </li>
  <li data-bind="with: getPerson() ">
    <p data-bind="text: $data.name"></p>
  </li>
  <li data-bind="with: getPerson() ">
    <p data-bind="text: $data.name"></p>
  </li>
</ul>

使用Javascript:

function PersonVM() {
  this.people = ko.observableArray([{
      name: "bob",
      age: 22
    },
    {
      name: "bill",
      age: 23
    },
    {
      name: "sue",
      age: 24
    },
  ])
  this.getPerson = function() {
    var random = Math.floor(Math.random() * this.people().length);
    var randomPerson = this.people()[random];
    this.people.remove(randomPerson);
    console.log(this.people().length);
    return randomPerson;
  }
}
ko.applyBindings(PersonVM, document.getElementById("personList"));

这只是输掉了2个人并留下了第三个空白。如果查看控制台日志,则数组长度为2,0,0。

为什么.remove会删除所有对象而不是已用过的对象?

1 个答案:

答案 0 :(得分:0)

正如@Matt所说,你正在触发getPerson重新评估。这就是原因:

你有一个带有observableArray的虚拟机,你将它绑定到你的视图。视图中有getPerson的3个绑定。在呈现视图时,它调用getPerson函数,但在每次调用时,它都会改变people observableArray。该变异会触发视图重新渲染,因为虚拟变量会发生变化。

您正在使用从列表中返回随机人员的函数,因此没有理由让人员数组可观察。当您想要在更改时驱动视图更新时,您只需要可观察的属性。在这种情况下,它不仅不必要,而且还会造成意想不到的副作用。

解决方案1:

一个简单的解决方法是将people属性设置为普通数组:

function PersonVM() {
  this.people = [{
      name: "bob",
      age: 22
    },
    {
      name: "bill",
      age: 23
    },
    {
      name: "sue",
      age: 24
    },
  ]
  this.getPerson = function() {
    var random = Math.floor(Math.random() * this.people.length);
    var randomPerson = this.people[random];
    this.people.splice(random, 1);
    console.log(this.people.length);
    return randomPerson;
  }
}

您需要使用splice,因为JS Arrays没有删除方法。

解决方案2:

作为替代方法,您可以保留observableArray并从普通JS数组中以随机顺序填充它。然后你可以有一个更简单的视图绑定