Javascript 使用主干关系数据库在主干中创建嵌套模型
我希望在我的应用程序中使用嵌套模型 我已经能够按照文档中的示例创建嵌套对象(例如一对多关系)。但是,我不知道如何以更新上层对象的方式绑定下层元素。我认为一个实用的应用程序将是一个非常有用的教程 因此,我的问题是:如何使用Javascript 使用主干关系数据库在主干中创建嵌套模型,javascript,backbone.js,backbone-relational,Javascript,Backbone.js,Backbone Relational,我希望在我的应用程序中使用嵌套模型 我已经能够按照文档中的示例创建嵌套对象(例如一对多关系)。但是,我不知道如何以更新上层对象的方式绑定下层元素。我认为一个实用的应用程序将是一个非常有用的教程 因此,我的问题是:如何使用主干关系扩展,以便: 可以为每个项目添加/删除子项目 双击任何子项都会对其进行编辑(就像最初的Todo示例一样) 单击项目可隐藏/显示其子项目 子项不是单独获取的,只是Todo项的数组属性 更新:我有。到目前为止,我已经: 导入了上面提到的Todo示例 创建了一个Todos
主干关系扩展
,以便:
- 可以为每个项目添加/删除子项目
- 双击任何子项都会对其进行编辑(就像最初的Todo示例一样)
- 单击项目可隐藏/显示其子项目
- 子项不是单独获取的,只是Todo项的数组属性
- 导入了上面提到的Todo示例
- 创建了一个
模型和一个TodosBitem
集合TodosBitemList
- 将
模型更改为扩展Todo
而不是RelationalModel
,其中model
与
todousibitem
- 在html代码中添加了一个子项模板
- 为
子项添加一个输入字段,该字段仅在单击
div时显示Todo
- 将子项数据作为
对象的属性,但仍有Todo
将DOM元素绑定到它们(例如todosBitemView
标记)
,这样一个Todo就可以有0..*子对象,以及0..1父对象
通过这种方式,您可以重复使用顺序逻辑(如果您将其更改为“应用于每个集合”),可以根据需要创建更深的嵌套级别(或者将其限制到某个深度,如果您愿意的话),等等。但是,为了适应这一点,需要更新许多内容-例如,保留一个子视图列表,这样您就可以对它们进行循环,将每个视图标记为已完成,并根据TodoList
维护(和更新)顺序
无论如何,一个可能的解决方案的大致轮廓可以让您开始,作为与当前版本的一种区别(抱歉,它完全未经测试,因此可能包含可怕的错误):
//我们的基本**Todo**模型有'text'、'order'和'done'属性。
window.Todo=Backbone.RelationalModel.extend({
关系:[{
类型:Backbone.HasMany,
关键词:“儿童”,
相关模型:“待办事项”,
collectionType:“TodoList”,
反向关联:{
键:'父',
includeInJSON:“id”
}
}],
初始化:函数(){
if(!this.get('order')&&this.get('parent')){
set({order:this.get('parent').nextChildIndex()});
}
},
//todo项目的默认属性。
默认值:函数(){
返回{done:false};
},
//切换此待办事项的“完成”状态。
切换:函数(){
this.save({done:!this.get(“done”)});
}
nextChildIndex:function(){
var children=this.get('children');
返回children&&children.length | 0;
}
});
//todo项目的DOM元素。。。
window.TodoView=Backbone.View.extend({
//…是一个列表标记。
标记名:“li”,
//缓存单个项的模板函数。
模板:35;.template($('#项模板').html()),
//特定于项的DOM事件。
活动:{
“单击”:“切换子项”,
'按键输入.添加子项':'添加子项',
“单击。检查”:“切换完成”,
“dblclick div.todo-text”:“编辑”,
“单击span.todo销毁”:“清除”,
“按键。待办事项输入”:“更新输入”
},
//TodoView侦听对其模型的更改,然后重新渲染。
初始化:函数(){
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={};
},
//重新呈现todo项的内容。
render:function(){
html(this.template(this.model.toJSON());
这个.setText();
//当然,您可能想将其添加到模板中
this.el.append(“”,{class':'children'}).append(“”,{type:'text',class':'addchild'});
_.each(this.get('children')、函数(child){
这个.renderChild(child);
},这个);
归还这个;
},
addChild:函数(文本){
如果(e.keyCode==13){
var text=this.el.find('input.add child').text();
var child=newtodo({parent:this.model,text:text});
}
},
renderChild:函数(模型){
var childView=newtodoview({model:model});
this.childView[model.cid]=childView;
this.el.find('ul.children').append(childView.render());
},
toggleChildren:function(){
$(this.el).find('ul.children').toggle();
},
//切换模型的“完成”状态。
toggleDone:function(){
this.model.toggle();
_.each(this.childview,function(child){
child.model.toggle();
});
},
清除:函数(){
this.model.set({parent:null});
this.model.destroy();
}
//等等。。。
});
我认为您无法在主干关系中创建自相关模型(如本文中的另一个答案所述)。当我尝试这一点时,我得到了一个错误:主干关系需要先定义relatedModel,然后才能创建与它的关系
所以,我修改了ma
//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...
});
Person = Backbone.RelationalModel.extend({
relations: [
{
type: 'HasMany',
key: 'Children',
relatedModel: 'FamilyRelation',
reverseRelation: {
key: 'Childrenof'
}
},
{
type: 'HasMany',
key: 'Parent',
relatedModel: 'FamilyRelation',
reverseRelation: {
key: 'Parentof'
}
}
]
});
// 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'});
KingKong.get("children").add({"parentof":SonOfKong});
var theModel = Backbone.RelationalModel.extend({ [...] });
theModel.prototype.relations.push({
type: Backbone.HasOne,
key: 'key',
relatedModel: theModel
});