collection.fetch()中显式上下文丢失

时间:2014-06-05 08:09:37

标签: javascript jquery backbone.js

我尝试将视图对象作为上下文传递给fetch回调:

var List = Backbone.Collection.extend({
    url: '/tree/list.php'
});
var list = new List();

var View = Backbone.View.extend({
    test: 'ok',
    initialize: function() {
        list.fetch({
            context: this
        })
        .done(function(){
            alert(this.test);
        });
    }
});

var view = new View();

这样可以正常工作并提示“确定”,但是:

var List = Backbone.Collection.extend({
    url: '/tree/list.php'
});
var list = new List();

var View = Backbone.View.extend({
    test: 'ok',
    initialize: function() {
        list.fetch({
            context: this,
            success: function(){
                alert(this.test);
            }
        });
    }
});

var view = new View();

什么都不提醒。

在第二种情况下,尽管我显式传递context参数,为什么上下文会丢失?

3 个答案:

答案 0 :(得分:2)

这是因为在第一个示例中,您将回调附加到Collection.fetch返回的jqXHR,后者尊重Backbone.ajax传递给它的上下文参数。

您的第二个示例将成功回调传递给Collection,而Collection又由Backbone调用,而不是jQuery。因此忽略了上下文参数。看一下Backbone源代码就证实了这一点:

fetch: function(options) {
      options = options ? _.clone(options) : {};
      if (options.parse === void 0) options.parse = true;
      var success = options.success;
      var collection = this;
      options.success = function(resp) {
        var method = options.reset ? 'reset' : 'set';
        collection[method](resp, options);
        if (success) success(collection, resp, options);
        collection.trigger('sync', collection, resp, options);
      };
      wrapError(this, options);
      return this.sync('read', this, options);
    },

在骨干网中,建议您使用事件和Backbone.View提供的listenTo方法。此方法确保在调用事件处理程序时上下文正确,并且每当使用backbone.View.remove()移除视图时都会删除侦听器:

var MyView = Backbone.View.extend({
  test: 'ok',
  initialize: function(){
    this.collection = new Backbone.Collection({url:'/endpoint');
    this.listenTo(this.collection, 'sync', this.onSync);
  },
  onSync: function(){
    alert(this.test); // Works
  }
})

答案 1 :(得分:0)

最有可能发生这种情况是因为在调用成功函数时会丢失上下文。成功的背景是窗口元素。如果你想将此传递给成功,请在初始化函数中创建var self = this,然后再执行alert(self.test)

var View = Backbone.View.extend({
    test: 'ok',
    initialize: function() {
    var self = this;

        list.fetch({

            success: function(){
                alert(self.test);
            }
        });
    }
});

作为替代方案,您也可以这样做:

var View = Backbone.View.extend({
    test: 'ok',
    initialize: function() {
        list.fetch({
            context: this,
            success: function(collection,response,options){
                alert(options.context.test);
            }
        });
    }
});

答案 2 :(得分:0)

我相信这应该有效:

var View = Backbone.View.extend({

    test: 'ok',

    initialize: function() {
        var that = this;

        list.fetch({
            // context: this,
            success: function(){
                alert(that.test);
            }
        });
    }
});

问题是this正在使用的内容。

在你的第二个例子中,this看起来像是指向传递给list.fetch()的对象文字(包含contextsuccess属性的对象),这不是没有一个名为test的属性,因此它会提醒undefined