2012-12-03 18 views
8

Mi trovo su un isssue quando provo a creare una collezione di collezioni usando backbone js. Ecco il codice:Backbone js collezione di numeri di emissione

Modelli e Collezioni:

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, 
}) 

creazione della collezione 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())) 

Ecco l'output:

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

Il problema è, come possiamo vedere sull'output, le 2 playlist hanno le 2 tracce "fur elise" e "fuy" un".

Quindi la mia domanda è: perché? e cosa dovrei fare per avere "pelliccia elisa" solo nella prima playlist denominata "classico" e "fuya" solo nella seconda playlist chiamata "c2c"?

Grazie.

risposta

8

Credo che il problema è il vostro difetto tracks attributo nella PlayList:

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

Backbone sarà poco profonde copiare il defaults durante la creazione di nuove istanze:

defaultmodel.defaults or model.defaults()
[.. .]
Ricorda che in JavaScript, oggetto s vengono passati per riferimento, quindi se includi un oggetto come valore predefinito, sarà condiviso tra tutte le istanze.

Il risultato è che ogni singolo PlayList esempio che utilizza il difetto tracks userà esattamente TrackCollection come attributo tracks e che TrackCollection sarà quello riferimento nel defaults.

La soluzione più semplice è quella di utilizzare una funzione per defaults:

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

In questo modo la funzione defaults verrà chiamato quando sono necessari valori predefiniti e ogni volta che viene chiamato defaults si otterrà un nuovo TrackCollection nel attributo predefinito tracks.

ecco una rapida regola empirica per voi:

Se si vuole mettere qualcosa di diverso da stringhe, numeri o booleani in defaults, utilizzare una funzione defaults invece di un oggetto defaults.

+0

Hai perfettamente ragione, ho pensato che stava eseguendo una copia dei valori predefiniti durante l'istanziazione. Comunque, grazie mille per la tua risposta! – Kraoz

+0

questa è una grande informazione e molto pertinente, ma potrebbe essere semplicemente più facile e più chiaro creare una nuova collezione nel metodo di inizializzazione? –

+1

@AlexMills: Forse.Non sapevo abbastanza della loro situazione da dire. Questa risposta è più di un "se hai intenzione di fare questo, quindi fallo in questo modo" in un certo senso. –