【问题标题】:Backbone js collection of collections issue骨干js集合问题
【发布时间】:2012-12-03 00:20:16
【问题描述】:

当我尝试使用主干 js 创建集合集合时遇到了问题。 这是代码:

模型和集合:

var Track = Backbone.Model.extend({

    defaults : {
      title : ""
    }
})

var TrackCollection = Backbone.Collection.extend({

    model : Track,
})

var Playlist = Backbone.Model.extend({

    defaults : {
        name : "",
        tracks : new TrackCollection,
    }
})

var PlaylistCollection = Backbone.Collection.extend({

    model : Playlist,
})

创建播放列表集合:

var playlists = new PlaylistCollection;

// create and push the first playlist
playlists.push({ name : "classic" });
// create and push a track in the playlist just created
playlists.last().get("tracks").push({ title : "fur elise" });

// create and push the second playlist
playlists.push({ name : "c2c" });
// create and push a track in the playlist just created
playlists.last().get("tracks").push({ title : "fuya" });

// display first playlist
console.log(JSON.stringify(playlists.at(0).toJSON()))
// display second playlist
console.log(JSON.stringify(playlists.at(1).toJSON()))

这是输出:

{"name":"classic","tracks":[{"title":"fur elise"},{"title":"fuya"}]}
{"name":"c2c","tracks":[{"title":"fur elise"},{"title":"fuya"}]}

问题是,正如我们在输出中看到的那样,2 个播放列表有 2 个曲目“fur elise”和“fuya”。

所以我的问题是为什么?我应该怎么做才能让“fur elise”只出现在名为“classic”的第一个播放列表中,而“fuya”只出现在名为“c2c”的第二个播放列表中?

谢谢。

【问题讨论】:

    标签: collections backbone.js


    【解决方案1】:

    我认为您的问题是PlayList 中的默认tracks 属性:

    var Playlist = Backbone.Model.extend({
        defaults : {
            name : "",
            tracks : new TrackCollection,
        }
    });
    

    Backbone 在创建新实例时将浅拷贝defaults

    默认值 model.defaults or model.defaults()
    [...]
    请记住,在 JavaScript 中,对象是通过引用传递的,因此如果您将对象作为默认值包含在内,它将在所有实例之间共享。

    结果是每个使用默认tracksPlayList 实例都将使用与其tracks 属性完全相同的TrackCollection,并且TrackCollection 将是defaults 中引用的那个@ .

    最简单的解决方案是使用defaults 的函数:

    var Playlist = Backbone.Model.extend({
        defaults : function() {
            return {
                name : "",
                tracks : new TrackCollection,
            };
        }
    });
    

    这样defaults 函数将在需要默认值时被调用,并且每次调用defaults 时,您都会在默认的tracks 属性中获得一个全新的TrackCollection

    这里有一个快速的经验法则:

    如果您想在defaults 中放入除字符串、数字或布尔值以外的任何内容,请使用defaults 函数而不是defaults 对象。

    【讨论】:

    • 你说得对,我认为它是在实例化时复制默认值。无论如何,非常感谢您的回复!
    • 这是很好的信息并且非常中肯,但是在初始化方法中创建一个新的集合可能更容易、更清晰吗?
    • @AlexMills:也许吧。我对他们的情况了解得还不够多。这个答案更像是“如果你要这样做,那么就这样做”之类的事情。
    • 谢谢 Mu,给你一个问题 - 我想质疑你所说的关于默认值作为对象而不是默认值作为函数的事情。在我的一个模型中,我的默认值是一个对象,并且我的所有默认属性都是空值,但这并不意味着当我创建该模型的新实例时,所有其他先前创建的实例值都变为空值。这怎么能与你所说的共享单一价值相吻合?
    • @AlexMills: null 是不可变的,数组或对象不是:jsfiddle.net/7z0c7f6e
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    相关资源
    最近更新 更多