首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >多个模型子类的Backbone.js集合

多个模型子类的Backbone.js集合
EN

Stack Overflow用户
提问于 2011-08-04 05:28:04
回答 4查看 15.2K关注 0票数 63

我有一个REST Json API,它返回一个列表“logbook”。有许多类型的日志实现了不同但相似的行为。这在数据库层的服务器端实现是一种单表继承,因此日志的每个JSON表示都包含它的“类型”:

代码语言:javascript
复制
[
  {"type": "ULM", "name": "My uml logbook", ... , specific_uml_logbook_attr: ...},
  {"type": "Plane", "name": "My plane logbook", ... , specific_plane_logbook_attr: ...}
]

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

代码语言:javascript
复制
class Logbook extends Backbone.Model

class UmlLogbook extends Logbook

class PlaneLogbook extends Logbook

...

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

代码语言:javascript
复制
class LogbookCollection extends Backbone.Collection
  model: Logbook
  url: "/api/logbooks"

当我获取日志集合时,有没有一种方法可以将每个类型转换为其相应的子类(基于JSON“Logbook”属性)?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-08-04 07:52:55

确实有。

当你在一个集合上调用'fetch‘时,它会在将其添加到集合之前通过Backbone.Collection.parse传递响应。

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

代码语言:javascript
复制
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

编辑:哇,idbentley比我早到了。唯一的区别是他使用了'each‘,而我使用了'map’。这两种方法都可以工作,但不同。

使用'each‘有效地打破了'fetch’调用启动的链条(通过返回'undefined‘--随后对'reset’(或'add')的调用将不做任何事情),并在解析函数中执行所有处理。

使用'map‘只是将属性列表转换为模型列表,并将其传递回已在运动的链。

不同的笔划。

再次编辑:刚刚意识到还有另一种方法:

集合上的' model‘属性存在只是为了让集合知道如何在'add’、'create‘或'reset’中传递属性时创建一个新模型。所以你可以这样做:

代码语言:javascript
复制
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'

这样做的好处是,集合现在将知道如何为“fetch”以外的操作“转换”日志的正确子类。

票数 81
EN

Stack Overflow用户

发布于 2011-08-04 07:37:21

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

代码语言:javascript
复制
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":
               ...
          }
      }
    }
 });

希望这能有所帮助。

票数 11
EN

Stack Overflow用户

发布于 2012-04-01 00:32:47

从backbone 0.9.1开始,我已经开始使用esa-matti suuronen的pull-request中描述的方法:

https://github.com/documentcloud/backbone/pull/1148

应用补丁后,您的集合将如下所示:

代码语言:javascript
复制
LogbookCollection = Backbone.Collection.extend({

    model: Logbook,

    createModel: function (attrs, options) {
        if (attrs.type === "UML") { // i'am assuming ULM was a typo
            return new UmlLogbook(attrs, options);
        } else if (attrs.type === "Plane") {
            return new Plane(attrs, options);
        } else {
            return new Logbook(attrs, options);
            // or throw an error on an unrecognized type
            // throw new Error("Bad type: " + attrs.type);
        }
    }

});

我相信这是合适的,因为您使用的是STI (所有型号都有唯一的i)

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6933524

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档