在淘汰赛中没有完全绑定

时间:2012-11-01 04:52:52

标签: javascript data-binding knockout.js knockout-2.0

Knockout无法正常工作,我的界面。 我想我的错误。但我无法理解。

我有一个包含流派的流派的专辑:

var initialData = [{
    title: 'Danny',
    genres: [
        {id: 21,
        title: 'Noise'},
        {id: 22,
        title: 'EBM'}],
    tracks: [
        {title: 'Pony',
        genres: [
            {id: 21,
            title: 'Noise'},
            {id: 22,
            title: 'EBM'}]},
        {title: 'Hungry',
        genres: [
            {id: 21,
            title: 'Noise'},
            {id: 22,
            title: 'EBM'}]}
    ]

}];

我想在专辑类型之间创建单向同步以跟踪流派:

  • 如果我在专辑中添加流派,则此类型将添加到所有曲目中。
  • 如果我从相册中删除流派,则会从所有曲目中删除此类型。
  • 如果我将音轨添加到音轨,则此类型将仅添加到此音轨。
  • 如果我从曲目中删除流派,则只会从此曲目中删除此流派。

使用此功能,我的同步工作正常(除了一个案例):

self.addGenre = function(album) {
    var id = rand(),
        item = {
            id: id,
            title: ' genre #' + id
        };
    album.genres.push(item);

    if (album.tracks()) {
        $.each(album.tracks(), function (index, track) {
            track.genres.push(item);
        });
    }
};

self.removeGenre = function(genre) {
    $.each(self.albums(), function() {
        this.genres.remove(genre);
        if (this.tracks()) {
            $.each(this.tracks(), function (index, track) {
                track.genres.remove(genre);
            });
        }
    });
};

例外情况是我要从相册中删除默认(Noise,EBM,请参阅上面的initialData)类型。它不起作用。

我创建了一个jsFiddle来展示这种情况并在其中包含了很多console.log()来调试

1 个答案:

答案 0 :(得分:1)

问题在于,当您使用ko-mapping时,它会将每个属性转换为可观察的属性。您创建的新类型与初始对象不是同一类型的对象,因为它们只是标准的vanilla对象。因此,您尝试从曲目中删除的流派与您从相册中删除的流派不同。

解决问题的一种简单方法是更改​​删除功能,如this fiddle

$.each(this.tracks(), function(index, track) {
    var toRemove = ko.utils.arrayFirst(track.genres(), function(item) {
        return ko.utils.unwrapObservable(genre.id) == ko.utils.unwrapObservable(item.id);
    });
    track.genres.remove(toRemove);
});

更好的方法是在生成初始视图模型,新类型或两者时更加彻底。这并不容易。