![](/img/trans.png)
[英]Is there a way to bind an event to all nested models with Backbone and/or Backbone-Relational?
[英]Creating nested models in Backbone with Backbone-relational
我想使用backbone-relational在我的backbone.js应用程序中使用嵌套模型。
我已经能够按照文档中的示例来创建嵌套对象(例如,一对多关系)。 但是我不明白如何以更新上层对象的方式绑定较低级别的元素。 我认为一个有用的应用程序将是一个非常有用的教程。
所以我的问题是:如何使用backbone-relational
扩展Todos教程,以便:
更新 :我为这个问题创建了一个jsfiddle 。 到目前为止,我有:
TodoSubitem
模型和TodoSubitemList
集合 Todo
模型以扩展RelationalModel
而不是Model
,与TodoSubitem
具有HasMany
关系 subitem-template
但我仍然不确定如何:
subitems
添加输入字段,仅在单击Todo
div时显示 Todo
对象的属性,但仍然有TodoSubitemView
将DOM元素绑定到它们(例如<li>
标签)。 在这种情况下,我不认为我会创建一个单独的'TodoSubItem' - 为什么不从Todo-> Todo创建一个HasMany
关系,所以Todo可以有0 .. * children
parent
,0..1 parent
?
这样,您可以重新使用订单逻辑(如果您将其更改为每个集合应用),可以根据需要创建更深的嵌套级别(或者如果您还需要将其限制到某个深度),等等。事情需要更新,以适应这一点 - 例如,保留一个子视图列表,以便您可以循环它们以将每个视图标记为已完成,并维护(和更新)每个TodoList
的排序。
无论如何,大概是一个可能的解决方案,让你开始,作为你当前版本的一种差异(对不起,它是完全未经测试,因此可能包含可怕的错误):
//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...
});
我不认为你可以在Backbone-relational中创建自相关模型(如此处的另一个答案所述)。 当我尝试这个时,我得到一个错误:Backbone-relational需要在它可以与之建立关系之前定义relatedModel。
所以,我修改了骨干关系页面上描述的多对多模式:
https://github.com/PaulUithol/Backbone-relational#many-to-many-relations
本质上,我正在创建一个链接模型来包含对所引用模型的引用,以便在定义实际模型时,此链接模型可用于Backbone-relational。
我发现将此链接模型与关系中的两个数据模型分开设置是很方便的,这样可以执行查看关系查找。 或者,您可以简单地将第二个模型填充到链接模型中,但是除非您在数据模型中明确地将链接模型添加到链接模型中,否则关系将是一个方向。
让我们创建一个“人”模型,其中包含其他“人”模型的子项。
Person = Backbone.RelationalModel.extend({
relations: [
{
type: 'HasMany',
key: 'Children',
relatedModel: 'FamilyRelation',
reverseRelation: {
key: 'Childrenof'
}
},
{
type: 'HasMany',
key: 'Parent',
relatedModel: 'FamilyRelation',
reverseRelation: {
key: 'Parentof'
}
}
]
});
需要在<Person之前>定义FamilyRelation,因此Backbone-relational可以创建链接,因此这将在代码中的Person模型定义之前进行:
// FamilyRelation is link model between two "Person"s
// to achieve the Fan/Admiree relation.
FamilyRelation = Backbone.RelationalModel.extend({
})
如果我们创建两个“人”:
KingKong = new Person({name: 'KingKong'});
SonOfKong = new Person({name: 'SonOfKong'});
然后我们可以创建一个FamilyRelationship模型,它是'parentof'SonOfKong,并使用以下行将其添加到KingKong的孩子:
KingKong.get("children").add({"parentof":SonOfKong});
然后,您可以向Person模型添加便利函数,从FamilyRelationship模型中检索嵌套模型,并且不再需要再触摸FamilyRelation,除了确保正确保存和检索它。
对于非层次关系(比如'朋友',而不是'父/子'),你仍然需要这两个与链接模型的关系,以便能够从另一个中检索一个,这有点像黑客,但是有用。
在一些摆弄之后,我找到了一种创建真正嵌套模型的方法:
var theModel = Backbone.RelationalModel.extend({ [...] });
theModel.prototype.relations.push({
type: Backbone.HasOne,
key: 'key',
relatedModel: theModel
});
在使用模型的时候(当推到原型上的关系时),它是可用的,从而使一切工作。
这篇文章现在已经很老了,但我正在寻找相同的东西,并认为我会分享我得到的解决方案。
要创建自引用模型,只需省略relatedModel
。 所以像这样:
Person = Backbone.RelationalModel.extend({ relations: [{ type: 'HasMany', key: 'Children', }] })
它在文档中解释
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.