骨干从外部json填充集合

时间:2013-12-15 04:06:08

标签: javascript json backbone.js

下面是我手工构建的集合的现有代码结构。我在我的服务器上有一个json文件,我现在正在尝试加载它,基本上删除手册并根据该数据构建一个集合。想知道我可能需要在下面更改我的代码来帮助解决这个问题。

        var Game = Backbone.Model.extend({
            defaults: {
                name: 'John Doe',
                age: 30,
                occupation: 'worker'
            }
        });


        var GameCollection = Backbone.Collection.extend({
            model: Game,
            url: 'path/to/json',

            parse: function(response) {
                return response;
            }
        });

        var GamesView = Backbone.View.extend({
            tagName: 'ul',

            render: function() {
                //filter through all items in a collection
                this.collection.each(function(game){
                    var gameView = new GameView({model: game});
                    this.$el.append(gameView.render().el);
                }, this)

                return this;
            }
        });

        var GameView = Backbone.View.extend({
            tagName: 'li',

            template: _.template($('#gameTemplate').html()),

            render: function() {
                this.$el.html(this.template(this.model.toJSON()));
                return this;
            }
        });

        var gameCollection = new GameCollection([
            {
                name: 'John Doe',
                age: 30,
                occupation: 'worker'
            }, 
            {
                name: 'John Doe',
                age: 30,
                occupation: 'worker'
            }, 
            {
                name: 'John Doe',
                age: 30,
                occupation: 'worker'
            }
        ]);

        var gamesView = new GamesView({collection: gameCollection});

        $(document.body).append(gamesView.render().el);

3 个答案:

答案 0 :(得分:10)

这是关于Backbone的众多事情之一。我不知道你的后端使用了什么,但是你声明你的服务器上有一个json文件,希望你的json文件中充满了应该在你的集合中的模型。现在这里是魔法代码(鼓请...):

var GameCollection = Backbone.Collection.extend({
  model: Game,
  url: 'path/to/json/on/external/server',
});

var gameCollection = new GameCollection();
gameCollection.fetch();

不多,对吧?当然,您可以添加或更改fetch几个选项,因此请查看此处的文档:http://backbonejs.org/#Collection-fetch。 Backbone默认使用jQuery.ajax(),因此请查看此处的文档以查看所有选项:http://api.jquery.com/jQuery.ajax/

除非服务器上的型号与主干型号不匹配,否则您的集合中不应该使用自定义解析。

要知道的事情fetch是异步的。与服务器通信需要时间,其余的javascript将继续并完成。您可能至少需要在success选项中添加一个回调函数,该选项将在fetch完成时调用,并且最好向error添加一些内容,情况出错了。您可以将数据添加为查询字符串,以便后端可以使用data选项使用它,数据必须是对象。这是一个例子:

gameCollection.fetch({
  data: {collection_id: 25},
  success: function(){
    renderCollection(); // some callback to do stuff with the collection you made
  },
  error: function(){
    alert("Oh noes! Something went wrong!")
  }
});

fetch应该以JSON格式接收数据,因此您的网址应该独占返回JSON,或者设置为检测AJAX请求并使用JSON响应它。

答案 1 :(得分:1)

首先,你需要从服务器上获取它,就像RustyToms所说的那样。另一个考虑因素是如何从服务器收集数据时强制集合视图再次呈现自身,如muistooshort评论。

如果您操纵fetchsync,当应用中有多个集合时,您需要多次执行此操作。

这样做是Marionette原生的,但在简单的Backbone中,你可以模仿Marionette的CollectionView的方法,并且这样做:

//For the collection view
var GamesView = Backbone.View.extend({
  initialize: function({
    this.listenTo(this.collection, 'reset', this.render, this);
  });
  // Others
});

然后,当从服务器获取集合数据时,集合将触发reset事件,集合视图会注意到此事件并再次自我渲染。

对于多个集合,您可以将代码解压缩到app中的父对象中并从中继承。

var App.CollectionView = Backbone.View.extent({
  initialize: //code as above
});

var GamesView = App.CollectionView.extend({
  //Your code without initialize
});

答案 2 :(得分:0)

我知道此时此刻有点陈旧,但我想回答其他坚持此事的人。

代码似乎来自此处的教程:http://codebeerstartups.com/2012/12/a-complete-guide-for-learning-backbone-js/

我也重新使用了该教程中的演示应用程序,并且无法使用外部数据进行渲染。

首先是数据本身需要转换为有效的JSON,否则会出现.parse()错误。

SyntaxError: JSON.parse: expected property name or '}' at line 3 column 9 of the JSON data

error:  SyntaxError: Unexpected token n

在数据源文件中,对象属性需要用引号括起来。看起来应该是这样的:

[
  {
    "name": "John Doe",
    "age": 30,
    "occupation": "worker"
  },
  {
    "name": "John Doe",
    "age": 30,
    "occupation": "worker"
  },
  {
    "name": "John Doe",
    "age": 30,
    "occupation": "worker"
  }
]

其次,一旦明确外部数据正在加载,我们需要让它进行渲染。我通过将render()命令移动到gameCollection.fetch()的成功函数中解决了这个问题(可能是不合理的)。

gameCollection.fetch({
  success: function(collection, response, options) {
    console.log('Success!! Yay!!');
    $(document.body).append(gamesView.render().el);
  },
  error: function(collection, response, options) {
    console.log('Oh, no!');
    // Display some errors that might be useful
    console.error('gameCollection.fetch error: ', options.errorThrown);
  }
});

当然有更好的方法可以实现这一目标,但是这种方法可以直接将教程中学习的代码转换为适用于外部数据的代码。