多个模型子类的 Backbone.js 集合 [英] A Backbone.js Collection of multiple Model subclasses

查看:18
本文介绍了多个模型子类的 Backbone.js 集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<预><代码>[{"type": "ULM", "name": "My uml logbook", ... , specific_uml_logbook_attr: ...},{"type": "Plane", "name": "我的飞机日志", ... , specific_plane_logbook_attr: ...}]

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

class Logbook 扩展了 Backbone.Model类 UmlLogbook 扩展日志类飞机日志扩展日志...

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

class LogbookCollection 扩展 Backbone.Collection型号: 日志网址:/api/日志"

当我获取 logbook 集合时,有没有办法将每个 Logbook 转换为其相应的子类(基于 JSONtype"属性)?

解决方案

确实有.

当您对集合调用fetch"时,它会在将响应添加到集合之前通过 Backbone.Collection.parse 传递响应.

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

class Logbooks 扩展了 Backbone.Collection型号: 日志网址:'api/日志'解析: (resp, xhr) ->_(resp).map (attrs) ->切换属性类型当 'UML' 然后是新的 UmlLogbook attrs当 'Plane' 然后新的 PLaneLogbook attrs

哇,idbentley 在我之前到达那里.唯一的区别是他使用每个"而我使用地图".两者都可以,但不同.

使用each"有效地打破了fetch"调用开始的链(通过返回undefined"——因此对reset"(或add")的后续调用将什么都不做)并在那里完成所有处理在解析函数中.

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

不同的笔画.

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

集合上的 'model' 属性仅存在于集合中,如果它在 'add'、'create' 或 'reset' 中传递属性,则该集合知道如何创建新模型.所以你可以这样做:

class Logbooks 扩展了 Backbone.Collection模型:(属性,选项)->切换属性类型当 'UML' 然后是新的 UmlLogbook attrs, options当 'Plane' 然后新的 PLaneLogbook attrs, options# 应该在这里添加一个'else',这样就有一个默认值,如果,# 比如说,没有为 Logbooks.create 调用提供属性网址:'api/日志'

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

I have a REST Json API that returns a list "logbooks". There are many types of logbooks that implement different but similar behavior. The server side implementation of this on the Database layer is a sort of Single Table Inheritance, so each JSON representation of a logbook contains its "type" :

[
  {"type": "ULM", "name": "My uml logbook", ... , specific_uml_logbook_attr: ...},
  {"type": "Plane", "name": "My plane logbook", ... , specific_plane_logbook_attr: ...}
]

I would like to replicate this server model on the client side, so I have a base Logbook class and multiple logbook sub classes :

class Logbook extends Backbone.Model

class UmlLogbook extends Logbook

class PlaneLogbook extends Logbook

...

My Backbone.Collection is a set of Logbook models that i use to query the JSON API :

class LogbookCollection extends Backbone.Collection
  model: Logbook
  url: "/api/logbooks"

When I fetch the logbook collection, is there a way to cast each Logbook to its corresponding sub class (based on the JSON "type" attribute) ?

解决方案

There is indeed.

When you call 'fetch' on a collection, it passes the response through Backbone.Collection.parse before adding it to the collection.

The default implementation of 'parse' just passes the response through, as is, but you can override it to return a list of models to be added to the collection:

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

EDIT: whoa, idbentley got there before me. the only difference being he used 'each' and I used 'map'. Both will work, but differently.

Using 'each' effectively breaks the chain that the 'fetch' call started (by returning 'undefined' - the subsequent call to 'reset' (or 'add') therefore will do nothing) and does all the processing right there in the parse function.

Using 'map' just transforms the list of attributes into a list of models and passes it back to the chain already in motion.

Different strokes.

EDIT AGAIN: just realized there's also another way to do this:

The 'model' attribute on a collection is there only so the collection knows how to make a new model if it's passed attributes in 'add', 'create' or 'reset'. So you could do something like:

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'

The advantage of this is that the collection will now know how to 'cast' the right subclass of Logbook for operations other than 'fetch'.

这篇关于多个模型子类的 Backbone.js 集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆