javascript 使用 Backbone-relational 在 Backbone 中创建嵌套模型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7227597/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Creating nested models in Backbone with Backbone-relational
提问by Christopher DuBois
I would like to use backbone-relationalto have nested models in my backbone.jsapplication.
我想使用backbone-relational在我的backbone.js应用程序中嵌套模型。
I have been able to follow the examples in the documentation to create nested objects (e.g. one-to-many relations). However I don't understand how to bind the lower level elements in a way that will update the upper level objects. I think a working application would be a very helpful tutorial.
我已经能够按照文档中的示例创建嵌套对象(例如一对多关系)。但是我不明白如何以更新上层对象的方式绑定下层元素。我认为一个有效的应用程序将是一个非常有用的教程。
So my question is: How do I extend the Todos tutorialusing backbone-relational
so that:
所以我的问题是:如何使用以下方式扩展Todos 教程backbone-relational
:
- one can add/remove subitems for each item
- double clicking on any subitem edits it (just like the original Todo example)
- clicking on an item hides/reveals its subitems
- subitems are not fetched separately but are simply an array attribute of Todo items
- 可以为每个项目添加/删除子项目
- 双击任何子项对其进行编辑(就像原始 Todo 示例一样)
- 点击一个项目隐藏/显示其子项目
- 子项不会单独获取,而只是 Todo 项的数组属性
Update: I have created a jsfiddle for this question. So far I have:
更新:我为这个问题创建了一个 jsfiddle。到目前为止,我有:
- Imported the Todo example mentioned above
- Created a
TodoSubitem
model and aTodoSubitemList
collection - Altered the
Todo
model to extendRelationalModel
instead ofModel
, with aHasMany
relation toTodoSubitem
- Added a
subitem-template
in the html code
- 导入上面提到的Todo例子
- 创建了一个
TodoSubitem
模型和一个TodoSubitemList
集合 - 改变了
Todo
模型扩展RelationalModel
,而不是Model
,有HasMany
关系TodoSubitem
subitem-template
在html代码中添加了一个
But I'm still not sure how to:
但我仍然不确定如何:
- add an input field for
subitems
that appears only when you click aTodo
div - have subitem data as an attribute of
Todo
objects, but still haveTodoSubitemView
bind DOM elements to them (e.g.<li>
tags).
- 添加一个
subitems
仅在您单击Todo
div时出现的输入字段 - 将子项目数据作为
Todo
对象的属性,但仍将TodoSubitemView
DOM 元素绑定到它们(例如<li>
标签)。
采纳答案by Paul
I don't think I'd create a separate 'TodoSubItem' in this case - why not create a HasMany
relation from Todo->Todo, so a Todo can have 0..* children
, and 0..1 parent
?
我不认为在这种情况下我会创建一个单独的“TodoSubItem”——为什么不HasMany
从 Todo->Todo创建一个关系,这样一个 Todo 可以有 0..*children
和 0..1 parent
?
This way, you can re-use the order logic (if you change it to apply per collection), can create deeper nesting levels as desired (or limit that to a certain depth, if you want as well), etc. A number of things will need to be updated though, to accomodate this - for example, keep a list of child views so you can loop over them to mark each as done, and maintaining (and updating from) an ordering per TodoList
.
这样,您可以重新使用顺序逻辑(如果您将其更改为应用到每个集合),可以根据需要创建更深的嵌套级别(或将其限制为某个深度,如果您愿意的话)等。事情需要更新,以适应这一点 - 例如,保留一个子视图列表,以便您可以遍历它们以将每个视图标记为已完成,并维护(和更新)每个TodoList
.
Anyway, a rough outline of a possible solution to get you started, as a sort of diff with your current version (sorry, it's completely untested and could thus contain horrible mistakes):
无论如何,粗略概述一个可能的解决方案来帮助您入门,作为与您当前版本的一种差异(抱歉,它完全未经测试,因此可能包含可怕的错误):
//Our basic **Todo** model has `text`, `order`, and `done` attributes.
window.Todo = Backbone.RelationalModel.extend({
relations: [{
type: Backbone.HasMany,
key: 'children',
relatedModel: 'Todo',
collectionType: 'TodoList',
reverseRelation: {
key: 'parent',
includeInJSON: 'id'
}
}],
initialize: function() {
if ( !this.get('order') && this.get( 'parent' ) ) {
this.set( { order: this.get( 'parent' ).nextChildIndex() } );
}
},
// Default attributes for a todo item.
defaults: function() {
return { done: false };
},
// Toggle the `done` state of this todo item.
toggle: function() {
this.save({done: !this.get("done")});
}
nextChildIndex: function() {
var children = this.get( 'children' );
return children && children.length || 0;
}
});
// The DOM element for a todo item...
window.TodoView = Backbone.View.extend({
//... is a list tag.
tagName: "li",
// Cache the template function for a single item.
template: _.template($('#item-template').html()),
// The DOM events specific to an item.
events: {
'click': 'toggleChildren',
'keypress input.add-child': 'addChild',
"click .check" : "toggleDone",
"dblclick div.todo-text" : "edit",
"click span.todo-destroy" : "clear",
"keypress .todo-input" : "updateOnEnter"
},
// The TodoView listens for changes to its model, re-rendering.
initialize: function() {
this.model.bind('change', this.render, this);
this.model.bind('destroy', this.remove, this);
this.model.bind( 'update:children', this.renderChild );
this.model.bind( 'add:children', this.renderChild );
this.el = $( this.el );
this.childViews = {};
},
// Re-render the contents of the todo item.
render: function() {
this.el.html(this.template(this.model.toJSON()));
this.setText();
// Might want to add this to the template of course
this.el.append( '<ul>', { 'class': 'children' } ).append( '<input>', { type: 'text', 'class': 'add-child' } );
_.each( this.get( 'children' ), function( child ) {
this.renderChild( child );
}, this );
return this;
},
addChild: function( text) {
if ( e.keyCode == 13 ) {
var text = this.el.find( 'input.add-child' ).text();
var child = new Todo( { parent: this.model, text: text } );
}
},
renderChild: function( model ) {
var childView = new TodoView( { model: model } );
this.childViews[ model.cid ] = childView;
this.el.find( 'ul.children' ).append( childView.render() );
},
toggleChildren: function() {
$(this.el).find( 'ul.children' ).toggle();
},
// Toggle the `"done"` state of the model.
toggleDone: function() {
this.model.toggle();
_.each( this.childViews, function( child ) {
child.model.toggle();
});
},
clear: function() {
this.model.set( { parent: null } );
this.model.destroy();
}
// And so on...
});
回答by Jon Biz
I don't think you can make self-relating models in Backbone-relational (as described an the other answer here). When I have tried this, I get an error: Backbone-relational needs the relatedModel to be defined before it can create relationships with it.
我认为您不能在 Backbone-relational 中创建自相关模型(如此处的另一个答案所述)。当我尝试此操作时,出现错误:Backbone-relational 需要先定义相关模型,然后才能与其建立关系。
So, I've modified the many-to-many pattern described on the backbone-relational page:
所以,我修改了主干关系页面上描述的多对多模式:
https://github.com/PaulUithol/Backbone-relational#many-to-many-relations
https://github.com/PaulUithol/Backbone-relational#many-to-many-relations
In essence, I am creating a linking model to contain references to the model being referred to, so that this link model can be available to Backbone-relational when it is defining the actual model.
本质上,我正在创建一个链接模型来包含对所引用模型的引用,以便在定义实际模型时,此链接模型可用于 Backbone-relational。
I find it convenient to give this link model a separate relationship with both data models in the relationship, so that either can perform look relational look ups. Alternately, you could simply stuff the second model inside the link model, but then the relationship would be one directional unless you explicitly add your own references to the link model in the data model.
我发现给这个链接模型一个单独的关系与关系中的两个数据模型很方便,这样任何一个都可以执行查找关系查找。或者,您可以简单地将第二个模型填充到链接模型中,但除非您在数据模型中明确添加自己对链接模型的引用,否则关系将是单向的。
Let us create a 'Person' model that has children who are other 'Person' models.
让我们创建一个“人”模型,其中包含其他“人”模型的子代。
Person = Backbone.RelationalModel.extend({
relations: [
{
type: 'HasMany',
key: 'Children',
relatedModel: 'FamilyRelation',
reverseRelation: {
key: 'Childrenof'
}
},
{
type: 'HasMany',
key: 'Parent',
relatedModel: 'FamilyRelation',
reverseRelation: {
key: 'Parentof'
}
}
]
});
FamilyRelation needs to be defined >before< Person is, so Backbone-relational can create the links, so this goes before the Person model definition in your code:
FamilyRelation 需要在 >before< Person 之前定义,所以 Backbone-relational 可以创建链接,所以这在代码中的 Person 模型定义之前:
// FamilyRelation is link model between two "Person"s
// to achieve the Fan/Admiree relation.
FamilyRelation = Backbone.RelationalModel.extend({
})
If we create two "Person"s:
如果我们创建两个“人”:
KingKong = new Person({name: 'KingKong'});
SonOfKong = new Person({name: 'SonOfKong'});
Then we can create a FamilyRelationship model that is the 'parentof' SonOfKong, and add it to KingKong's children with this line:
然后我们可以创建一个 FamilyRelationship 模型,它是 SonOfKong 的“父母”,并使用以下行将其添加到 KingKong 的孩子:
KingKong.get("children").add({"parentof":SonOfKong});
You can then add convenience functions to the Person model, to retrieve the nested models from the FamilyRelationship model, and don't really need to touch FamilyRelation any more, except to make sure it's being saved and retrieved appropriately.
然后,您可以向 Person 模型添加便利函数,以从 FamilyRelationship 模型中检索嵌套模型,并且实际上不再需要接触 FamilyRelation,除非确保它被正确地保存和检索。
For non-hierarchical relationships (say 'Friend', rather than 'Parent/Child', you still need these two relationships with the linking model in order to be able to retrieve one from the other, which is a bit of a hack, but it works.
对于非层次关系(比如“朋友”,而不是“父/子”,您仍然需要使用链接模型的这两个关系才能从另一个关系中检索一个,这有点麻烦,但是有用。
回答by Ronald Mansveld
After some fiddling I have found a way to create a true nested model:
经过一番折腾,我找到了一种创建真正嵌套模型的方法:
var theModel = Backbone.RelationalModel.extend({ [...] });
theModel.prototype.relations.push({
type: Backbone.HasOne,
key: 'key',
relatedModel: theModel
});
At the point where the model is used (when pushing to the relations on the prototype) it is available, thus making everything work.
在使用模型时(当推送到原型上的关系时)它可用,从而使一切正常。
回答by tvdw
this post is pretty old by now, but I was searching for the same thing and thought I would share the solution I got.
这篇文章现在已经很老了,但我正在寻找同样的东西,并认为我会分享我得到的解决方案。
To create a self-referencing model you simply omit relatedModel
. So something like this:
要创建自引用模型,您只需省略relatedModel
. 所以像这样:
Person = Backbone.RelationalModel.extend({
relations: [{
type: 'HasMany',
key: 'Children',
}]
})
Person = Backbone.RelationalModel.extend({
relations: [{
type: 'HasMany',
key: 'Children',
}]
})
It is explained in the docs
它在文档中解释