【问题标题】:Backbone response SOMETIMES returns empty骨干网响应有时返回空
【发布时间】:2012-05-14 20:03:25
【问题描述】:

Backbone 存在不一致的问题。我在我的集​​合的 fetch 方法中添加了一个 console.log,所以我知道服务器总是提供数据,但有时我的视图无法看到该信息,或者显示 this.model.models.length 到为零,当我知道 fetch 返回了对象时。

我不知道为什么我会在 fetch 和尝试查看它们之间删除对象,所以希望有人能提供帮助。

我的路由器是这样的:

Router = Backbone.Router.extend({
    routes: {
       ""              : "index",
       "/"             : "index",
       "testing"       : "index",
       "follow/:type/" : "follow"
    },

    follow: function(type) {
        switch(type) {
            case "companies":
               this.followedItems = new FollowedCompanies();
               break;
            case "software":
               this.followedItems = new FollowedSoftware();
               break;
            case "hardware":
               this.followedItems = new FollowedHardware();
               break;
            case "tags":
               this.followedItems = new FollowedTags();
               break;
            case "people":
               this.followedItems = new FollowedPeople();
               break;
            default:
        }
        title = type.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
        this.followedItems.fetch({
            success: function(data) {
            },
            error: function(data) {
                console.log("Error: " + data);
            }
        });
        this.followView = new FollowView({
            model: this.followedItems,
            el: $("#activityFeed"),
            title: title
        });
    }
});

    var router = new Router();
    Backbone.history.start();

Model/Controller,为了简洁,只剪了一个,但都是一样的,甚至有一个不一致:

var FollowedSoftware = Backbone.Collection.extend({
    url: '/api/v1/follow_software/?format=json',
    model: TestFollowing,
    parse: function(resp) { 
          console.log(resp.objects); 
          return resp.objects; 
    }
});

我的观点是这样的:

var FollowView = Backbone.View.extend({
    template: _.template($("#FollowHeaderTemplate").html()),
    initialize: function() {
        var self = this;
        $(self.el).slideUp('fast', function() {
            self.model.fetch(); // Put here for to help?  Doesn't matter if it's here or not really. 
            $(self.el).html(self.render());
        });
        $(self.el).slideDown('slow');
        // this.model.reset();
    },
    render: function() {
        var self = this;
        $(this.el).html(new FollowHeaderView().render({title: this.options.title}).el);
        console.log(this.model.models);
        $(self.el).append(new FollowHeaderView({title: this.options.title}).render());
        _.forEach(this.model.models, function(item) {
             $(self.el).append(new FollowedItemView({model: item}).render().el);
        });
    }
})

var FollowHeaderView = Backbone.View.extend({
    template: _.template($("#FollowHeaderTemplate").html()),
    render: function() {
        $(this.el).html(this.template({"title": title}));
        return this;
    }
})

var FollowedItemView = Backbone.View.extend({
    template : _.template( $("#FollowedTemplate").html()),
    render: function() {
        $(this.el).html(this.template({"item" : this.model.toJSON()}))
        return this;
    }
});

即使只是执行“软件”路线,有时它会起作用,有时却不起作用。 fetch 中的 console.log 方法总是返回工作数据,但视图中的 console.log 只是有时这样做。

我没有在客户端或服务器上的任何地方缓存任何东西,但我无法使这项工作始终如一。在我的 .fetch 调用中,我添加了成功和错误回调,但错误回调永远不会触发。我没有在任何地方覆盖同步。我使用的是 0.9.2 的 Backbone,提供服务器由 Django-Tastypie 提供支持,它运行良好(并且在其他一些具有相同代码的模型上也运行良好。)

可能与 switch 语句有关,但我不知道它会如何,并且为每个“类型”定义一个路由似乎很愚蠢(尽管如果必须的话我会这样做)。

我错过了什么吗?

【问题讨论】:

    标签: jquery backbone.js tastypie


    【解决方案1】:

    在从服务器完成获取模型之前,您正在访问视图中的模型。尝试在fetch 调用的success 回调中初始化您的视图。

    例如

    var my = this;
    this.followedItems.fetch({
      success: function(model) {
        my.followView = new FollowView({
          model: model,
          el: $("#activityFeed"),
          title: title
        });
      }
    });
    

    【讨论】:

      【解决方案2】:

      在路由器的follow 方法结束时,您正在调用 fetch,然后立即初始化您的视图。您应该初始化视图,对集合调用 fetch,然后将视图的 render 方法绑定到集合的 "reset" 事件。流程是异步的,应进行相应处理。

      这是一个绑定到reset 事件的示例,而不是必须在 fetch 上实现成功/错误方法(您通常不必这样做)。

      var FollowView = Backbone.View.extend({
          template: _.template($("#FollowHeaderTemplate").html()),
          initialize: function() {
              var self = this;
              $(self.el).slideUp('fast', function() {
                  self.model.fetch(); // Put here for to help?  Doesn't matter if it's here or not really. 
                  $(self.el).html(self.render());
              });
              $(self.el).slideDown('slow');
      
              // **ADDED BY lupefiasco**
              self.model.on('reset', function() {
                  self.render();
              }, this);
          },
          render: function() {
              var self = this;
              $(this.el).html(new FollowHeaderView().render({title: this.options.title}).el);
              console.log(this.model.models);
              $(self.el).append(new FollowHeaderView({title: this.options.title}).render());
              _.forEach(this.model.models, function(item) {
                   $(self.el).append(new FollowedItemView({model: item}).render().el);
              });
          }
      })
      

      旁注

      您在每次调用路由/follow/:type 时都重新初始化视图,这非常好,但是您需要在初始化新视图之前取消绑定旧视图。所以做这样的事情。

      if (this.followView != null) {
           this.followView.off(); // old view is now unbound
      }
      this.followView = new FollowView();
      

      您不需要在构造函数中传入视图的根元素。只需通过el 属性在视图中定义它,Backbone 就会自动为您设置$el(“jQuerified”版本)。

      var FollowedItemView = Backbone.View.extend({
          template : _.template( $("#FollowedTemplate").html()),
          el: '#activityFeed',
          render: function() {
                  this.$el.html(this.template({"item" : this.model.toJSON()}))
                  return this;
          }
      });
      

      您正在通过model 属性将您的集合传递给视图,而您应该通过collection 属性将它传递给视图。我认为这在功能方面没有太大区别,但它是 best practice

      【讨论】:

      • remove 应该可以解决问题:this.followView.remove()
      • remove 也会删除根元素,因此当您不需要保留根元素以备将来查看时,它的效果最佳。
      • @lupefiasco - 出色的答案,感谢所有其他提示。非常感谢,它现在肯定可以可靠地工作。
      • @bmelton:如果视图正在查看集合,那么您应该使用this.collection 而不是this.model。并且不需要_.forEach(this.collection.models),因为集合中已经混合了一堆下划线,您可以改为this.collection.each(...)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-25
      • 2018-05-13
      • 1970-01-01
      • 2013-02-10
      相关资源
      最近更新 更多