0

我试图在一段时间后(从视图中调用)切换我的 Backbone 集合(“帖子”)中的状态变量,并尝试使用 setTimeout。但是,我认为我搞砸了我的范围,因为我的切换功能不起作用(它被调用,但它没有正确改变)。

如果我使用

setTimeout(this.model.collection.toggleReadyToPreloadNewPost, 1000);

,代码不起作用,而如果我使用

this.model.collection.toggleReadyToPreloadNewPost();

它正确切换它。我想知道我该如何解决这个问题?

骨干视图

//ensures namespace is not already taken yet
wedding.views = wedding.views || {};

//each PostView corresponds to a single post container 
//which contains the user name, user comment, and a photo
wedding.views.PostView = Backbone.View.extend({

  tagName: "li",
  template: "#item-template",
  className: "hideInitially post",

  initialize: function() {
    _.bindAll(this);
    this.template = _.template($(this.template).html());
  },

  render: function() {
    this.preload();
    return this;
  },

  //preloads an image and only after it is done, then append
  preload: function() {
    var image = new Image(); 
    image.src = this.model.get("src");
    this.model.incrementTimesSeen();

    //hides the element initially, waits for it to finish preloading, then slides it down
    //updates lastSeen only after the image is displayed
    image.onload = $.proxy(function() {
      var html = this.template( {model: this.model.toJSON()} );

      this.model.setLastSeen();

      //shows the image by sliding down; once done, remove the hideInitially class
      this.$el.hide().append(html).slideDown();
      this.$el.removeClass("hideInitially");

      setTimeout(this.model.collection.toggleReadyToPreloadNewPost, 1000);
    }, this);
  }

});

骨干集合

//check if namespace is already occupied
wedding.collections = wedding.collections || {}; 

wedding.collections.Posts = Backbone.Collection.extend({
  model: wedding.models.Post,

  initialize: function() {
    this.readyToPreloadNewPost = 1;
  },

  //toggles "readyToPreloadNewPost" between 1 and 0 
  toggleReadyToPreloadNewPost: function() {

    this.readyToPreloadNewPost = this.readyToPreloadNewPost ? 0 : 1;
  }    
});
4

1 回答 1

2

当你这样做时:

setTimeout(this.model.collection.toggleReadyToPreloadNewPost, 1000);

您只是在处理setTimeout普通的未绑定toggleReadyToPreloadNewPost函数,setTimeout并将其作为简单函数调用。结果是调用函数时this会在window里面。toggleReadyToPreloadNewPostsetTimeout

您可以this通过将方法调用包装在匿名函数中来获得正确的权利:

var _this = this;
setTimeout(function() {
    _this.model.collection.toggleReadyToPreloadNewPost();
}, 1000);

您还可以使用_.bind

setTimeout(
    _(this.model.collection.toggleReadyToPreloadNewPost).bind(this.model.collection),
    1000
);

您还可以_.bindAll在集合内部使用initialize以始终将该方法绑定到适当的this

wedding.collections.Posts = Backbone.Collection.extend({
    initialize: function() {
        _.bindAll(this, 'toggleReadyToPreloadNewPost');
        //...
    }

然后你原来的

setTimeout(this.model.collection.toggleReadyToPreloadNewPost, 1000);

应该做正确的事。如果你总是想被束缚,你只会想走这条路toggleReadyToPreloadNewPost,我可能会选择第一个。

于 2012-12-12T08:35:46.333 回答