Backbone.js 和嵌入式一对多关联

Posted

技术标签:

【中文标题】Backbone.js 和嵌入式一对多关联【英文标题】:Backbone.js and Embedded One-To-Many Associations 【发布时间】:2012-03-03 21:38:40 【问题描述】:

应用布局

我正在构建一个应用程序,可以在其中创建调查。每个调查都有多个问题。我将问题嵌入到调查模型中(在 Mongoid 中使用 embeds_many),因此调查可能如下所示:


  "id":    "4f300a68115eed1ddf000004",
  "title": "Example Survey",
  "questions": 
  [
    
      "id":      "4f300a68115eed1ddf00000a",
      "title":   "Please describe your experience with backbone.js", 
      "type":    "textarea"
    ,
    
      "title":   "Do you like it?", 
      "id":      "4f300a68115eed1ddf00000b",
      "type":    "radiobutton",
      "options": ["Yes", "Yes, a lot!"]
    
  ]

现在,还有一个由SurveyView 组成的调查编辑器,用于显示调查并列出问题。如果我点击一个问题,会弹出一个QuestionView,我可以在其中编辑问题。当我对我的调查感到满意并单击保存时,SurveyModel 将被发送到服务器。

问题

处理嵌入式关联的最佳方式是什么?

如果我将survey.get("questions")[any_index] 传递给QuestionView,并且问题发生了变化,我必须在我的模型中手动搜索question.id 并更新我的模型。这感觉不对。

如果我在我的SurveyModel 中创建一个QuestionsCollection(这甚至可能吗?)。然后我可以做一些事情,比如通过 id 从这个集合中获取一个Question,将它传递给视图,当我更改模型时,一切都会自动更新,但我必须在集合中指定一个url,并且如果事情得到更新,主干将向服务器发送单个问题。

关于如何以主干方式执行此操作的任何建议?

【问题讨论】:

能否将最终代码粘贴到 javascript 中?不是咖啡师。谢谢。 【参考方案1】:

覆盖 parse/toJSON 是一个可行的解决方案。不过要注意的一个问题是,当通过集合获取对象时,parse 方法中的“this”不是模型对象。然后发生的是调用 parse 并将结果传递给初始化。您可能需要“this”来指向模型对象的原因是您想在集合上绑定事件。另一种方法是覆盖 set 方法。我提出了 a simple script on Github 来展示这种方法。

【讨论】:

【参考方案2】:

我认为你甚至可以在建筑中做到这一点

class Survey  extends Backbone.Model

initialize: ->
    @questions = new QuestionsCollection(@get('questions'))

您还可以通用扩展模型以获取嵌套数据:

_.extend Backbone.Model::, deepToJSON: ->
  obj = @toJSON()
  _.each _.keys(obj), (key) ->
    obj[key] = obj[key].deepToJSON()  if _.isFunction(obj[key].deepToJSON)

  obj

_.extend Backbone.Collection::, deepToJSON: ->
  @map (model) ->
    model.deepToJSON()

【讨论】:

【参考方案3】:

backbone.js 中嵌入一对多关联的方法

我已经实现了@Sander 的答案,只是想发布一些代码:

class Survey extends Backbone.Model

  # Handles the Survey.questions association to parse stuff from the server
  parse: (resp) ->
    if @attributes?.questions?
      @attributes.questions.reset(resp.questions)
    else
      resp.questions = new QuestionsCollection(resp.questions)
    resp

  # Recollects Survey.questions
  toJSON: ->
    attributes = _.clone(@attributes)
    attributes.questions = attributes.questions.toJSON()
    attributes

然后我可以做类似的事情:

survey = Survey.get("my-id")
survey.questions.at(0).title = "First question"
survey.questions.at(1).title = "Second question"
survey.save()

这很舒服。

【讨论】:

如果可以的话,我会给你+100万! 100 万 -1(对于丑陋的咖啡脚本 :))【参考方案4】:

您当然可以在您的 SurveyModel 中有一个 questionsCollection。

但您对被视为单个问题的问题是正确的(因为每个问题都应该有自己的 ID,所以仍然可以在服务器上知道它属于哪个调查...)

然后是你的 json 解析: 如果您手动构建集合和模型,则不会遇到此问题,但如果您添加嵌套 JSON,它不会自动为您的模型创建子集合。您需要在重写的 parse 方法中指定此类内容。

【讨论】:

以上是关于Backbone.js 和嵌入式一对多关联的主要内容,如果未能解决你的问题,请参考以下文章

将集合绑定到 Backbone.js 中的视图

与backbone.js的多对多关系事件

Backbone js代码味道 - 更好的嵌入子视图的方法?

如何使用 Apache DbUtils 获取一对多关联和父子类型关联?

hibernate一对多关联映射

Hibernate—— 一对多 和 多对多关联关系映射(xml和注解)总结(转载)