重写Backbone.js的加载动作

居然在Google里找不到类似的情况,难道只有我一个人会有这种疑问么……

我在使用Backbone的时候,遇到一个问题:我需要用 Backbone.Model 或者 Backbone.Collection 来加载一些远程数据,一般来说都是静态文件,比如HTML或者XML,既不满足RESTful,也不是JSON;虽然不很符合Backbone的要求,不过因为是静态的,所以我觉得ajax应该都没问题。当我按照这个思路写下去,一般就是这样:

var MyModelClass = Backbone.Model.extend({
  url: 'config.xml',
  parse: function (response) {
    console.log(response);
  }
});
var model = new MyModelClass();
model.fetch();

但是运行之后,我发现被覆盖的 parse 没有执行。然而查看网络,目标文件已经被正常加载。作为Backbone的初学者,也不知道问题出在哪里。不得已找来源码跟踪,发现Backbone实现 fetch 是委托给 Backbone.sync 方法,但是在实现的时候会把数据格式设置为json:

// http://documentcloud.github.com/backbone/backbone.js
// Default JSON-request options.
var params = {type: type, dataType: 'json'};

而 jQuery 1.4版之后,会对返回的数据格式进行验证,如果不符合就抛出异常。所以当我那些不是 JSON 但声明是 JSON 的数据加载完毕后,jQuery 就会抛出异常,于是覆盖的parse也就不执行了。

如果远程数据不是JSON,需要覆盖数据加载逻辑时,就应该覆写 .fetch(),比如这样:

var MyModelClass = Backbone.Model.extend({
  url: 'config.xml',
  fetch: function () {
    $.ajax({
      url: this.url,
      context: this,
      success: this.parse
    });
  }
  parse: function (response) {
    console.log(response);
  }
});

var model = new MyModelClass();
model.fecth();

我认为不应该重写 .sync(),因为实际应用中,不同的 Model 和 Collection 可能要提供加载远程数据、加载模板、与 LocalStorage 交互等不同的功能,重写sync也很难满足需要。所以不妨直接在不同的类里面覆盖各自的fetch、save方法。


这篇文章还有人看,那就更新一下。(2016-11-25)

Backbone 用的久了,发现它其实设计了更好的办法解决这种问题:调用 .fetch() 的时候传递 options

// 以下代码通过继承并覆写 .fetch() 方法,告知 jQuery 返回数据类型是 XML
var MyModel = Backbone.Model.extend({
  fetch: function (options) {
    options = options || {};
    options.dataType = 'xml';
    return Backbone.Model.prototype.fetch.call(this, options);
  },
  parse: function (response) {
    console.log(response); // jQuery 会帮我们分析这个 XML
  }
});

这种方式比上面的好得多。

如果您觉得文章内容对您有用,不妨支持我创作更多有价值的分享:


已发布

分类

来自

标签:

评论

《“重写Backbone.js的加载动作”》 有 4 条评论

  1. […] Backbone 0.9.1复写Collection的parse方法无效,不知道是为什么。 问题已解决:《重写Backbone.js的加载动作》 […]

  2. […] 重写Backbone.js的加载动作 分享到新浪微博腾讯微博豆瓣QQ空间FacebookTwitter This entry was posted in js and tagged backbone.js, JavaScript, jQuery, mvc, zepto.js, 笔记集 by meathill. Bookmark the permalink. […]

  3. 呆呆 的头像

    话说fetch的重写有种更优化的方法:
    fetch: function(options) {
    options = options || {};
    options.dataType=”xml”;
    Backbone.Collection.prototype.fetch.call(this, options);
    }

    1. meathill 的头像

      嗯,其实直接传个参数就好了

欢迎吐槽,共同进步

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据