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

发布于 2025-01-04 07:18:20 字数 1171 浏览 2 评论 0原文

应用程序布局

我正在构建一个应用程序,可以在其中创建调查。每项调查都有多个问题。我将问题嵌入到调查模型中(在 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,并且问题发生更改,我必须手动搜索 问题。 id 在我的模型中并更新我的模型。这感觉不对。

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

关于如何以骨干方式做到这一点有什么建议吗?

The App Layout

I am building an App, where one can create surveys. Every survey has multiple questions. I am embedding the questions into the survey model (with embeds_many in Mongoid), so a survey may look like this:

{
  "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!"]
    }
  ]
}

Now, there is also a survey editor which consists of a SurveyView, which displays the survey and lists the questions. If I click on a single question, a QuestionView will pop up, where I can edit the question. And when I am satisfied with my survey and I click save, the SurveyModel will be sent to the server.

The problem

What is the best way to handle the embedded association?

If I pass survey.get("questions")[any_index] to the QuestionView, and the question gets changed, I have to manually search for the question.id in my model and update my model. This feels wrong.

If I create a QuestionsCollection in my SurveyModel (is this even possible?). Then I can do things like fetching a Question out of this collection by id, pass it to the view and when I change the model, everything will get updated automatically, but I have to specify an url in the collection, and backbone will send single questions to the server, if things get updated.

Any suggestion on how to do this the backbone way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

东风软 2025-01-11 07:18:21

在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()

这工作起来很舒服。

The way to do embedded one-to-many associations in backbone.js

I have implemented the answer from @Sander and just wanted to post some code:

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

Then I can do stuff like:

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

Which works quite comfortable.

洒一地阳光 2025-01-11 07:18:21

您的 SurveyModel 中肯定可以有一个 questionsCollection。

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

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

you can most certainly have a questionsCollection inside your SurveyModel.

but you are right on the question being seen as a single question (since every question should have his own ID, it might still be possible to know on the server which survey it belongs to...)

then there is the parsing of your json:
if you are building your collection's and models manually you won't have this issue, but if you would add your nested JSON it will not automatically create a sub collection to your model. you would need to specify such things in an overridden parse method.

动次打次papapa 2025-01-11 07:18:21

我认为你甚至可以在构造时这样做

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()

I think you can even do that at contruction

class Survey  extends Backbone.Model

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

Also you can extend model universally to get the nested data:

_.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()
夜清冷一曲。 2025-01-11 07:18:21

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

Overriding parse/toJSON is a workable solution. One gotcha to be aware of though is that "this" in the parse method is not the model object when the object is fetched via a collection. What happens then is that parse is invoked and the result is passed to initialize. The reason you may need "this" to point to the model object is if you want to bind events on the collection. An alternative approach is to override the set method instead. I put up a simple script on Github that showcases this approach.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文