【问题标题】:Backbone.js collection fetching with JSON使用 JSON 获取 Backbone.js 集合
【发布时间】:2011-11-08 03:00:02
【问题描述】:

我正在使用 Backbone.js 和 Phil Sturgeon 的 CI 休息服务器(很棒的工具,绝对推荐)。

这是我的页面:http://interr0bang.net/7357/fetch/。很基础,一个模型(Event),一个集合(Events),一个视图(EventView)。 该集合位于http://api.interr0bang.net/calendar/events,并返回一个已使用 jsonformatter.curiousconcept.com 验证的 JSON 数组。

代码如下:

$(function(){
    var Event = Backbone.Model.extend();
    var Events = Backbone.Collection.extend({
        model: Event,
        url: 'http://api.interr0bang.net/calendar/events',

    });
    var EventView = Backbone.View.extend({
        initialize: function(){
            _.bindAll(this, "render","count");
            this.collection = new Events();
            this.collection.bind("change",this.count);
            this.collection.fetch();
            this.counter = this.collection.length;
            this.render();
        },
        render: function(){
            this.el.html(this.counter);
        },
        count: function(){
            this.counter = this.collection.length;
        }
    });
    eventView = new EventView({el:$('#collection')});
});

视图渲染正常,但是总是显示0,Firebug显示GET请求,状态为200 OK,但是响应体是空的……为什么这样不行?

【问题讨论】:

  • 在此示例中,尝试绑定到“更改”以更新项目的“计数”,这是毫无价值的。也许这在 11 年 9 月有效,但今天您将绑定到“添加”或“删除”

标签: json backbone.js


【解决方案1】:

您应该使用 JSONP hack 通过跨域获取 JSON 数据。

您可以覆盖 Backbone.js 同步工作:Using JSONP with Backbone.js

【讨论】:

    【解决方案2】:

    即使在子域之间,您也不能进行跨域 Ajax 调用...所以基本上,您的浏览器在域 interr0bang.net 上阻止了对域 api.interr0bang.net 上 API 的 Ajax 调用...这是JavaScript 警告的含义:

    Origin http://interr0bang.net is not allowed by Access-Control-Allow-Origin.
    

    您可以通过将 API 移至同一域来解决此问题,例如:http://interr0bang.net/api/calendar/events(如果可以)。

    如果您不能这样做,您可以通过在 API 方法的响应中包含一些标头来授权 Ajax 跨域调用。这是CORS 协议,它适用于大多数现代浏览器。

    这是另一个有关 CORS 的 StackOverflow 答案,解释了它的工作原理:JSONP and Backbone.js

    【讨论】:

    • 非常感谢您的输入,我实际上能够将 api 移动到同一个域
    【解决方案3】:

    我目前从您发布的两个 URL 中都收到错误消息。

    http://interr0bang.net/7357/fetch/ = 404
    http://api.interr0bang.net/calendar/events = 无法访问

    附带说明,我发现最好将事物尽可能分开(模型不应该知道视图,视图不应该知道模型等)。因此,我建议您不要在视图中实例化集合。

    以下是上述代码的重构实现:

    $(function(){
      var
        Event = Backbone.Model.extend({})
        ,Events = Backbone.Collection.extend({
          model: Event
          ,url: 'http://api.interr0bang.net/calendar/events'
        })
        ,EventView = Backbone.View.extend({
          initialize: function(){
            _.bindAll(this, 'count');
            this.collection.bind('all', this.count);
          }
          ,count: function() {
            this.el.html(this.counter = this.collection.length);
          }
        })
        ,events = new Events()
        ,eventView = new EventView({
          el: $('#collection')
          ,collection: events
        })
      ;
    
      events.fetch();
    });
    

    请注意我是如何将集合传递给视图而不是由它自己创建的。另请注意,我删除了渲染方法并将其与计数相结合。每当更改集合(添加、删除、重置)时,都会调用 count 并更新视图。

    【讨论】:

    • 如果您不到处使用逗号,那么对于初学者来说示例会更好。
    • 我编写代码的方式与我通常编写代码的方式相同。我不会尝试为最低公分母编码。如果有什么让您感到困惑,请随时要求澄清。这个怎么样? gist.github.com/3d64cba0a37783ad745a
    【解决方案4】:

    您有配置问题。如果您查看浏览器,它会报告:

    XMLHttpRequest cannot load http://api.interr0bang.net/calendar/events. Origin     
    http://interr0bang.net is not allowed by Access-Control-Allow-Origin.
    

    【讨论】:

    • 我在我的项目中遇到了同样的问题。你能告诉我你是如何解决这个问题的吗?
    猜你喜欢
    • 1970-01-01
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-29
    • 2013-07-27
    • 2012-05-10
    相关资源
    最近更新 更多