Backbone.js fetch() JSON to model get() returns un

2019-03-01 05:41发布

问题:

Basically I want to fetch a JSON file and store it in a model. However, when I try to access the attributes via get() it returns undefined. So lets say the JSON file has an array games that consists of objects with some attributes. It doesn't really matter. Just want to save them in the model and access them. So I'm doing something like this.

var player = Backbone.Model.extend({
   initialize: function(app, options) {
      this.app = app;
      var _this = this;

      this.fetch({
         url: "someurl",
         success: function() {
            console.log("success");
         }
      });
   }
});

var instplayer = new player();
instplayer.on('change', function(){
   console.log(model);
   console.log(model.get(games));
})

So I figured that I need an event to ensure that get() is called when the data is really available. But this still returns undefined. What do I need to do?

回答1:

So I imagined you have a json for your player like this (I've mocked it here for the example below to work):

{
    "username": "joe",
    "games": [
        {
            "title": "Pacman"
        }, {
            "title": "Super Mario" } 
    ]
}

And here's a complete working example of how I would deal with managing and rendering this kind of data:

var Game = Backbone.Model.extend({
  defaults: {
    title: ''
  }
});

var Games = Backbone.Collection.extend({
  model: Game
});

var Player = Backbone.Model.extend({
  defaults: {
    username: ''
  },
  url: 'http://www.mocky.io/v2/56261127250000a01accb34f',
  initialize: function(){
    this.games = new Games();
    this.listenTo( this, "sync", this.initGames );
    this.fetch();
  },
  initGames: function(){
    this.games.add( this.get('games') );
    this.trigger('ready', this);
  }
});

var PlayerView = Backbone.View.extend({
  template: _.template('<h1><%=username%></h1> and his games: <ol class="games"></ol>'),
  render: function(){
    this.$el.html( this.template( this.model.toJSON() ) );
    this.model.games.each( this.renderGame, this );
    return this;
  },
  renderGame: function(game, i){
    var gameView = new GameView({ model: game });
    gameView.render().$el.appendTo( this.$('.games') );
  }
});

var GameView = Backbone.View.extend({
  tagName: 'li',
  template: _.template('<strong>Game:</strong> <%=title%>'),
  render: function(){
    this.$el.html( this.template( this.model.toJSON() ));
    return this;
  }
});


var dude = new Player();
dude.on('ready', function(player){
  var playerView = new PlayerView({ model: player });
  playerView.render().$el.appendTo( document.body );
});
<script src='http://code.jquery.com/jquery.js'></script>
<script src='http://underscorejs.org/underscore.js'></script>
<script src='http://backbonejs.org/backbone.js'></script>



回答2:

I don't know if it's a typo or not but you are not passing model to the callback

instplayer.on('change', function(){
  console.log(model);
  console.log(model.get(games));
})

it should be

instplayer.on('change', function(model, options){
  console.log(model);
  console.log(model.get("games"));
})

then games must be a string not a variable.

Another thing I suggest you to be aware of is what the json returns; sometimes you have to override the parse function to get the exact results.

Again if your fetching an array and not a single object, maybe you should use a collection of players