Javascript Backbone.js 构建嵌套视图和模型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6353607/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
backbone.js structuring nested views and models
提问by fortuneRice
Using backbone.js:
使用backbone.js:
I have a top level ModelA that contains 2 attributes and 2 nested models, ModelB and ModelC. ModelB and ModelC each have 2 attributes as follows:
我有一个顶级 ModelA,它包含 2 个属性和 2 个嵌套模型,ModelB 和 ModelC。ModelB 和 ModelC 各有 2 个属性,如下所示:
ModelA
attributeA1
attributeA2
ModelB
attributeB1
attributeB2
ModelC
attributeC1
attributeC2
There is a ViewA for ModelA, and a ViewB for ModelB. ViewA's render function places a new div onto the body, whereas ViewB's render creates an h1. ViewA's initialization calls ViewB's render to insert that h1 into the new div. The rationale behind this separation is that the h1 may change and require re-rendering independent from ViewA.
ModelA 有一个 ViewA,ModelB 有一个 ViewB。ViewA 的render 函数在body 上放置一个新的div,而ViewB 的render 创建一个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 has a function funcB1. Can this function access it's parent model's attributes? Attributes such as attributeA1, or even attributeC1 (which would be a sibling/cousin)?
Q1:ViewB 有一个函数 funcB1。这个函数可以访问它的父模型的属性吗?诸如attributeA1,甚至attributeC1(这将是兄弟姐妹/表亲)之类的属性?
Q2: As a further expansion to Q1, can funcB1 access the DOM elements associated with ViewA? (in this example, the #new div?)
Q2:作为对Q1的进一步扩展,funcB1可以访问ViewA关联的DOM元素吗?(在这个例子中,#new div?)
Q3: In general, how do I define the associations between the Views and Models as described above so that everything ties together properly?
Q3:一般来说,我如何定义上面描述的视图和模型之间的关联,以便一切都正确地联系在一起?
I realize this question is somewhat abstract but any appreciate any help or guidelines appreciated.
我意识到这个问题有点抽象,但任何人都感谢任何帮助或指南。
回答by Jens Alm
To be able to reach attributes on related models, the model must have some kind of knowledge about what models it is related to. Backbone.js does not implicitly deal with relations or nesting, which means you must yourself make sure that the models have knowledge of each other. To answer your questions, one way to go about it is to make sure each child model has a 'parent' attribute. This way you can traverse the nesting first up to the parent and then down to any siblings that you know of.
为了能够获得相关模型的属性,模型必须对它所关联的模型有某种了解。Backbone.js 不会隐式处理关系或嵌套,这意味着您必须自己确保模型彼此了解。要回答您的问题,一种方法是确保每个子模型都具有“父”属性。通过这种方式,您可以首先遍历嵌套,然后遍历您知道的任何兄弟姐妹。
To be more specific with your questions. When initializing modelA, you are probably creating modelB and modelC, I would suggest setting a link to the parent model when doing this, like this:
更具体地说明你的问题。初始化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 way you can reach the parent model in any child model function by calling this.parent.
通过这种方式,您可以通过调用 this.parent 来访问任何子模型函数中的父模型。
Regarding your views, when doing nested backbone views, I find it easier to let each view represent one HTML tag by using the tagName option of the view. I would write your views as 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();
}
});
Then in your application initialization code (eg in your controller), I would initiate ViewA and place its element inside the body element.
然后在您的应用程序初始化代码中(例如在您的控制器中),我将启动 ViewA 并将其元素放在 body 元素中。
回答by Elf Sternberg
The general answer to the question "Can I" is always "yes, as long as you're willing to write the code." The point behind Backbone is to provide a strong separation of model and view. If B1 has a reference to A1, and A1 has a reference to C1, then you're fully capable of creating methods and setting the rules by which B1 can modify A1 and C1 and so forth.
“我能不能”这个问题的一般答案总是“是的,只要你愿意编写代码。” Backbone 背后的重点是提供模型和视图的强大分离。如果 B1 有 A1 的引用,而 A1 有 C1 的引用,那么您完全有能力创建方法并设置 B1 可以修改 A1 和 C1 的规则等等。
The views should be set up to receive CRUD events from their respective models. If the user does something with B1view that modifies B1model, and B1model in turn modifies A1model, then A1model should generate an event that A1view receives and causes a re-render of A1view, and so forth. It should happen like magic. (In practice, it takes some time to get the magic right, but I've found Backbone to be really powerful. And BackboneRelational helps with things like what you're describing here.)
视图应设置为从其各自的模型接收 CRUD 事件。如果用户对 B1view 做了一些修改 B1model 的事情,而 B1model 又修改了 A1model,那么 A1model 应该生成一个事件,A1view 接收并导致 A1view 的重新渲染,依此类推。它应该像魔术一样发生。(在实践中,需要一些时间才能正确使用魔法,但我发现 Backbone 非常强大。而 BackboneRelational 有助于解决您在此处描述的事情。)
回答by geddesign
The above solution is on the right track but has some problems.
上述解决方案是在正确的轨道上,但存在一些问题。
initialize: function(){
this.viewB = new ViewB();
this.viewB.parentView = this;
$(this.el).append(this.viewB.el);
}
Mainly, the model's toJSON() now returns stale data. I've posted a solution to fix this problem in a backbone.js plugin. You're welcome to use it.
主要是,模型的 toJSON() 现在返回陈旧数据。我已经在一个backbone.js 插件中发布了一个解决这个问题的解决方案。欢迎您使用它。
回答by Artem Oboturov
You can use some extensions, Backbone-Forms https://github.com/powmedia/backbone-formsfor example. To follow your use case define a schema like:
您可以使用一些扩展,例如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' }
}
});
Look at https://github.com/powmedia/backbone-forms#customising-templatesfor partial templates.
查看https://github.com/powmedia/backbone-forms#customising-templates了解部分模板。
Important parts here are type: 'NestedModel'
and template: 'templateXXX'
.
这里的重要部分是type: 'NestedModel'
和template: 'templateXXX'
。
This plugin has some limitations but you can look at others at https://github.com/documentcloud/backbone/wiki/Extensions%2C-Plugins%2C-Resources.
这个插件有一些限制,但你可以在https://github.com/documentcloud/backbone/wiki/Extensions%2C-Plugins%2C-Resources查看其他插件。
回答by Gagan
There is backbone plugin Backbone-relational.js which provides one-to-one, one-to-many and many-to-one relations between models for Backbone.
有一个主干插件 Backbone-relational.js,它为 Backbone 提供了模型之间的一对一、一对多和多对一关系。
I think this js will fulfill your needs. Vist BackboneRelationalfor more documentation.
我认为这个 js 将满足您的需求。访问BackboneRelational以获取更多文档。