Js 构造嵌套的视图和模型

使用 backbone.js:

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

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?

问题1: ViewB 有一个 function B1函数。这个函数可以访问它的父模型的属性吗?属性,例如 AttributeA1,或者甚至 AttributeC1(它是兄弟姐妹/堂兄弟姐妹) ?

Q2: 作为 Q1的进一步扩展,function B1能访问与 ViewA 相关的 DOM 元素吗?(在本例中,是 # new div?)

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

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

34163 次浏览

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

应该设置这些视图以从它们各自的模型接收 CRUD 事件。如果用户使用 B1视图修改 B1模型,而 B1模型反过来修改 A1模型,那么 A1模型应该生成一个事件,A1视图接收该事件并重新渲染 A1视图,以此类推。它应该像魔法一样发生。(在实践中,需要一些时间来获得魔术的权利,但我已经发现脊梁骨是真正强大的。BackboneRelational 可以帮助解决您在这里描述的问题。)

为了能够获得相关模型上的属性,模型必须具有与其相关的模型的某种知识。Js 不隐式地处理关系或嵌套,这意味着您必须自己确保模型之间具有相互的知识。要回答您的问题,一种方法是确保每个子模型都有一个“父”属性。通过这种方式,您可以首先遍历嵌套到父级,然后遍历到您所知道的任何兄弟姐妹。

更具体地问你的问题。在初始化 model A 时,您可能正在创建 model B 和 model C,我建议在这样做时设置一个到父模型的链接,如下所示:

ModelA = Backbone.Model.extend({


initialize: function(){
this.modelB = new modelB();
this.modelB.parent = this;
this.modelC = new modelC();
this.modelC.parent = this;
}
}

通过这种方式,您可以在任何子模型函数中访问父模型,方法是调用 This。

关于您的视图,在执行嵌套的主干视图时,我发现通过使用视图的 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 元素中。

上述解决方案是在正确的轨道上,但有一些问题。

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

主要是,模型的 toJSON ()现在返回过时的数据。我已经发布了一个解决方案,以解决这个问题在一个 Backbone js 插件。你可以用它。

您可以使用一些扩展,例如 Backbone-Formshttps://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 关系. js,它为骨干模型提供了一对一、一对多和多对一的关系。

我想这个 J 能满足你的需求。 访问 Backbone Relational了解更多文档。