Backbone.js多个Model子类的集合

Tri*_*ote 63 inheritance json coffeescript backbone.js

我有一个REST Json API,它返回一个列表"logbooks".有许多类型的日志可以实现不同但相似的行为.数据库层上的服务器端实现是一种单表继承,因此日志的每个JSON表示都包含其"类型":

[
  {"type": "ULM", "name": "My uml logbook", ... , specific_uml_logbook_attr: ...},
  {"type": "Plane", "name": "My plane logbook", ... , specific_plane_logbook_attr: ...}
]
Run Code Online (Sandbox Code Playgroud)

我想在客户端复制这个服务器模型,所以我有一个基Logbook类和多个日志子类:

class Logbook extends Backbone.Model

class UmlLogbook extends Logbook

class PlaneLogbook extends Logbook

...
Run Code Online (Sandbox Code Playgroud)

Backbone.Collection是一组Logbook用于查询JSON API的模型:

class LogbookCollection extends Backbone.Collection
  model: Logbook
  url: "/api/logbooks"
Run Code Online (Sandbox Code Playgroud)

当我获取日志集合时,有没有办法将每个元素Logbook转换为相应的子类(基于JSON"类型"属性)?

sat*_*run 81

的确有.

当您对集合调用'fetch'时,它会通过Backbone.Collection.parse传递响应,然后将其添加到集合中.

'parse'的默认实现只是传递响应,但您可以覆盖它以返回要添加到集合中的模型列表:

class Logbooks extends Backbone.Collection

  model: Logbook

  url: 'api/logbooks'

  parse: (resp, xhr) ->
    _(resp).map (attrs) ->
      switch attrs.type
        when 'UML' then new UmlLogbook attrs
        when 'Plane' then new PLaneLogbook attrs
Run Code Online (Sandbox Code Playgroud)

编辑:哇,idbentley在我面前到达那里.唯一的区别是他使用'each'而我使用'map'.两者都有效,但不同.

使用'each'有效地打破'fetch'调用开始的链(通过返回'undefined' - 后续调用'reset'(或'add')因此将不执行任何操作)并在解析中执行所有处理功能.

使用'map'只需将属性列表转换为模型列表,并将其传递回已经运动的链中.

不同的笔画.

再次编辑:刚才意识到还有另一种方法可以做到这一点:

集合中的"模型"属性只有这样,如果集合在"添加","创建"或"重置"中传递属性,集合就知道如何创建新模型.所以你可以这样做:

class Logbooks extends Backbone.Collection

  model: (attrs, options) ->
    switch attrs.type
      when 'UML' then new UmlLogbook attrs, options
      when 'Plane' then new PLaneLogbook attrs, options
      # should probably add an 'else' here so there's a default if,
      # say, no attrs are provided to a Logbooks.create call

  url: 'api/logbooks'
Run Code Online (Sandbox Code Playgroud)

这样做的好处是,该集合现在将知道如何为"fetch"以外的操作"强制转换"Logbook的正确子类.

  • 我建议你向上移动最后一部分让人们看到更多:)只是一个想法 (2认同)

idb*_*ley 11

是.你可以覆盖parse集合上的函数(我将使用javascript而不是coffeescript,因为它是我所知道的,但映射应该很简单):

LogbookCollection = Backbone.Collection.extend({
    model: Logbook,
    url: "/api/logbooks",
    parse: function(response){
      var self = this;
      _.each(response, function(logbook){
          switch(logbook.type){
             case "ULM":
               self.add(new UmlLogBook(logbook);
               break;
             case "Plane":
               ...
          }
      }
    }
 });
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.