我正在尝试从可观察数组中抓取一个随机对象,然后从数组中删除该对象,以便不再抓取它。但是,似乎所有对象都被删除得太快而且不正确,所以我用完了对象。
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会删除所有对象而不是已用过的对象?
答案 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数组中以随机顺序填充它。然后你可以有一个更简单的视图绑定