Knockout.js - 无法从可观察数组

时间:2015-04-26 04:12:02

标签: knockout.js knockout-mapping-plugin

我在新的应用程序中使用了淘汰赛一段时间,但直到最近我才手动创建对象来映射复杂的对象(以及它们的嵌套子对象)。然后我学习了映射插件,并开始使用它。我可以映射对象,并添加计算的observables等没有问题,但是当我从UI传回它时,我无法从可观察数组中删除它们。 remove会遍历数组,但永远不会找到要删除的(未编辑的)对象。同样地,我无法使用==和===与返回的对象进行比较并指定仅包含一个对象的数组的[0]位置来返回true。我认为这是导致它不能删除的原因,即使我认为它应该完全相同?

$(document).ready(function () {
    var viewModel = new appViewModel();

    $.ajax({
        type: "GET",
        url: "/api/Players",
    }).done(function (data) {
        viewModel.playersCollection(ko.mapping.fromJS(data));
    }).error(function (ex) {
        console.log("error retrieving players");
    });

    ko.applyBindings(viewModel);    
});    

视图模型

var appViewModel = function () {
    var self = this;
    this.playersCollection = ko.observableArray();

    this.confirmDeletePlayer = function (currentData) {
        self.playersCollection.remove(currentData);
    };
};

UI

<div data-bind="foreach: playersCollection()">
    <div>
        <span data-bind="text:Player.FirstName"></span>
        <span data-bind="click: $root.confirmDeletePlayer">
           <img src="delete-icon.png" />
        </span>
    </div>
</div>

我在这里做错了什么?

2 个答案:

答案 0 :(得分:1)

更改您的代码:

viewModel.playersCollection(ko.mapping.fromJS(data));

要:

viewModel.playersCollection = ko.mapping.fromJS(data);

或者:

viewModel.playersCollection(data);

playersCollection已经是一个可观察的数组,所以当你调用映射插件时,它会将data变成一个可观察的数组。所以你要将一个可观察的数组添加到一个可观察的数组中。我认为这会导致一些奇怪的问题。

请参阅:http://plnkr.co/edit/sYwSq3DEwf2sDSQj5s5B?p=preview

答案 1 :(得分:0)

这就是我要做的事情:

// request data as soon as possible, independent of document readiness
var playersReqest = $.get("/api/Players").fail(function (ex) {
    console.log("error retrieving players");
});

$(function () {
    // bind the vievmodel as soon as the view is ready
    var game = new GameViewModel();
    ko.applyBindings(game);    

    // as soon as the data is ready, map it into the viewmodel
    playersReqest.done(function (data) {
        ko.mapping.fromJS(data, {}, game.players);
    });
});    

function GameViewModel() {
    var self = this;
    self.players = ko.observableArray();

    self.deletePlayer = function (player) {
        self.players.remove(player);
    };
}

并且

<div data-bind="foreach: players">
    <div>
        <span data-bind="text: FirstName"></span>
        <span data-bind="click: $root.deletePlayer">
           <img src="delete-icon.png" />
        </span>
    </div>
</div>

注释

  • 绑定不需要手动展开值。 foreach: players已足够,foreach: players()是不必要的。
  • foreach: players为每个玩家对象设置上下文,因此内部可能是text: FirstName,而不是text: Player.FirstName(或者你有一个不洁的模型映射)。
  • 将Ajax请求,模型绑定和数据映射拆分为独立操作可确保每个步骤一旦准备就可以发生。