backbone.js构build嵌套的视图和模型

使用backbone.js:

我有一个顶级ModelA,它包含2个属性和2个嵌套模型ModelB和ModelC。 ModelB和ModelC各有两个属性如下:

ModelA attributeA1 attributeA2 ModelB attributeB1 attributeB2 ModelC attributeC1 attributeC2 

ModelA有ViewA,ModelB有ViewB。 ViewA的渲染函数将一个新的div放到body上,而ViewB的渲染函数创build一个h1。 ViewA的初始化函数调用ViewB的render来将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,甚至属性C1(这将是兄弟姐妹/表亲)?

Q2:作为Q1的进一步扩展,funcB1可以访问与ViewA相关的DOM元素吗? (在这个例子中,#new div?)

问题3:一般来说,我如何定义上述视图和模型之间的关联,以便所有东西都能正确地连接在一起?

我意识到这个问题是有点抽象的,但任何感谢任何帮助或指导。

为了能够涉及到相关模型的属性,模型必须对与其相关的模型有一定的了解。 Backbone.js并不隐式处理关系或嵌套,这意味着您必须确保模型具有彼此的知识。 要回答你的问题,一个方法就是确保每个子模型都有一个“父”属性。 这样,您可以先将嵌套遍历到父对象,然后再遍历到您所知道的任何兄弟对象。

更具体的你的问题。 当初始化modelA时,你可能正在创buildmodelB和modelC,我build议在这样做时设置一个到父模型的链接,如下所示:

 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元素中。

对于“我可以”这个问题的一般答案总是“是的,只要你愿意写代码”。 Backbone背后的重点是提供模型和视图的强大分离。 如果B1有一个A1的引用,A1有一个C1的引用,那么你完全有能力创build方法并设置B1可以修改A1和C1等等的规则。

这些意见应该被设置为从它们各自的模型接收CRUD事件。 如果用户使用B1view来修改B1model,B1model又会修改A1model,那么A1model应该生成一个A1view接收并导致A1view重新渲染的事件,依此类推。 它应该发生像魔术一样。 (在实践中,获得魔力需要一些时间,但是我发现Backbone是非常强大的,而BackboneRelational可以帮助你在这里描述的东西。)

上述解决scheme是正确的,但有一些问题。

 initialize: function(){ this.viewB = new ViewB(); this.viewB.parentView = this; $(this.el).append(this.viewB.el); } 

主要是,模型的toJSON()现在返回陈旧的数据。 我已经发布了一个解决scheme来解决这个问题在backbone.js插件 。 欢迎您使用它。

你可以使用一些扩展,例如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

骨干插件Backbone-relational.js提供了骨干模型之间的一对一,一对多和多对一的关系。

我认为这个JS会满足你的需求。 Vist BackboneRelational获取更多文档。