使用backbone.js:
我有一个顶级ModelA,它包含2个属性和2个嵌套模型,ModelB和ModelC。 ModelB和ModelC各有2个属性如下:
ModelA
attributeA1
attributeA2
ModelB
attributeB1
attributeB2
ModelC
attributeC1
attributeC2
ModelA有ViewA,ModelB有ViewB。 ViewA的渲染功能在主体上放置一个新的div,而ViewB的渲染创建一个h1。 ViewA的初始化调用ViewB的渲染将h1插入到新的div中。这种分离背后的基本原理是h1可能会发生变化,需要独立于ViewA重新渲染。
ViewA
initialise:
//call ViewA's own render function
this.render()
//call ViewB's render function that further modifies the $("#new") div created earlier.
$("#new").append(ViewB.render().el)
//ViewA's own render function
render: //place <div id="new"></div> onto 'body'
ViewB
render: //create a <h1></h1>
funcB1: //can this access it's parent ModelA's attributes and other objects?
Q1:ViewB有一个函数funcB1。这个函数可以访问它的父模型的属性吗?属性如attributeA1,甚至是attributeC1(可能是兄弟/堂兄)?
Q2:作为对Q1的进一步扩展,funcB1可以访问与ViewA相关的DOM元素吗? (在这个例子中,#new div?)
问题3:一般来说,如何定义视图和模型之间的关联,如上所述,以便一切正确地结合在一起?
我意识到这个问题有些抽象,但任何感谢任何帮助或指导都会感激。
答案 0 :(得分:73)
为了能够在相关模型上获得属性,模型必须具有与其相关的模型的某种知识。 Backbone.js不会隐式处理关系或嵌套,这意味着您必须自己确保模型彼此了解。要回答您的问题,一种方法是确保每个子模型都具有“父”属性。通过这种方式,您可以先遍历嵌套直到父级,然后再遍历到您知道的任何兄弟姐妹。
更具体地说明您的问题。在初始化modelA时,您可能正在创建modelB和modelC,我建议在执行此操作时设置父模型的链接,如下所示:
ModelA = Backbone.Model.extend({
initialize: function(){
this.modelB = new modelB();
this.modelB.parent = this;
this.modelC = new modelC();
this.modelC.parent = this;
}
}
这样,您可以通过调用this.parent。
来访问任何子模型函数中的父模型关于您的视图,在执行嵌套主干视图时,我发现通过使用视图的tagName选项让每个视图代表一个HTML标记更容易。我会把你的观点写成:
ViewA = Backbone.View.extend({
tagName: "div",
id: "new",
initialize: function(){
this.viewB = new ViewB();
this.viewB.parentView = this;
$(this.el).append(this.viewB.el);
}
});
ViewB = Backbone.View.extend({
tagName: "h1",
render: function(){
$(this.el).html("Header text"); // or use this.options.headerText or equivalent
},
funcB1: function(){
this.model.parent.doSomethingOnParent();
this.model.parent.modelC.doSomethingOnSibling();
$(this.parentView.el).shakeViolently();
}
});
然后在你的应用程序初始化代码中(例如在你的控制器中),我将启动ViewA并将其元素放在body元素中。
答案 1 :(得分:3)
“我可以”这个问题的一般答案是“是的,只要你愿意编写代码”。 Backbone背后的重点是提供模型和视图的强大分离。如果B1具有对A1的引用,并且A1具有对C1的引用,则您完全能够创建方法并设置B1可以修改A1和C1的规则,等等。
应设置视图以从各自的模型接收CRUD事件。如果用户使用B1view修改了B1model,而B1model依次修改了A1model,那么A1model应生成A1view接收的事件并导致重新呈现A1view,依此类推。它应该像魔术一样发生。 (在实践中,需要一些时间才能获得正确的魔力,但我发现Backbone非常强大。而BackboneRelational可以帮助解决你在这里所描述的内容。)
答案 2 :(得分:3)
上述解决方案已走上正轨但存在一些问题。
initialize: function(){
this.viewB = new ViewB();
this.viewB.parentView = this;
$(this.el).append(this.viewB.el);
}
主要是,模型的toJSON()现在返回陈旧数据。我已经发布了一个解决方案来解决backbone.js plugin中的问题。欢迎您使用它。
答案 3 :(得分:2)
您可以使用一些扩展名,例如Backbone-Forms https://github.com/powmedia/backbone-forms。要按照您的用例定义一个模式,如:
var ModelB = Backbone.Model.extend({
schema: {
attributeB1: 'Text',
attributeB2: 'Text'
}
});
var ModelC = Backbone.Model.extend({
schema: {
attributeC: 'Text',
}
});
var ModelA = Backbone.Model.extend({
schema: {
attributeA1: 'Text',
attributeA2: 'Text',
refToModelB: { type: 'NestedModel', model: ModelB, template: 'templateB' },
refToModelC: { type: 'NestedModel', model: ModelC, template: 'templateC' }
}
});
查看https://github.com/powmedia/backbone-forms#customising-templates部分模板。
此处的重要部分是type: 'NestedModel'
和template: 'templateXXX'
。
此插件有一些限制,但您可以在https://github.com/documentcloud/backbone/wiki/Extensions%2C-Plugins%2C-Resources查看其他人。
答案 4 :(得分:0)
主干插件Backbone-relational.js提供Backbone模型之间的一对一,一对多和多对一关系。
我认为这个js将满足您的需求。 Vist BackboneRelational获取更多文档。