了解 Backbone.js 中 MVC 的内部结构依赖 [英] Understanding the internal structural dependencies of MVC in Backbone.js

查看:16
本文介绍了了解 Backbone.js 中 MVC 的内部结构依赖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有点困惑 w.r.t.设计 MVC 时的结构依赖关系 - 所以我们有一个模型、集合和视图(我还没有使用控制器,但这个问题也适用于它).现在who has a reference of who 用面向对象的术语说话.所以集合是一个模型列表,所以我们可以把它看作是从集合到模型的一对多依赖.在一些示例代码中,我有时会看到对模型"对象中视图的一些引用以及视图中模型的引用.有时是视图中的集合.

在模型中我有时会看到一个 this.view 而在视图中我看到类似 this.model.view 或一个 this.model,从而混淆了澄清:)

那么什么是正确"的依赖集(如果有正确的"方式)或者每个人都可以依赖每个人(不要认为这是正确的),即理想情况下谁应该依赖谁在 Backbone 的 MVC 对象设计中?当我看到如此不同的例子时,知道它们应该如何在结构上相关 - 从菜鸟的角度来看,这有点令人困惑:) 作为菜鸟,开始构建我的依赖项的正确"方法是什么 - 一旦我开始学习曲线 我自己可能会弄明白,但首先,应该怎么做?一个类似 UML 的图表将是一个额外的好处;)

另一个问题:有时我会在同一段代码中看到两个视图:例如:著名的 todo.js http://documentcloud.github.com/backbone/docs/todos.html

现在虽然我明白需要多个视图,但令人困惑的是它们有什么不同?我的意思是el"和tagName"之间的区别是什么?如果它们中的任何一个不存在,视图的行为有何不同?我的意思是在上面的链接中,一个视图使用tagName"和另一个el",我不太确定它们是如何相关的(如果有的话).

我已经仔细阅读了文档,但正如我所说的,我仍在学习,所以即使有所有资源,我也可能无法清楚地理解其中的某些部分,并且可能需要一些人工干预 :)

解决方案

由于 Backbone.js 本身不是一个框架,因此没有单一的正确"方法可以做任何事情.但是,实现中有一些提示可以帮助您理解这个想法.此外,您还可以应用一些经过时间考验的通用代码组织实践.但我先解释一下观点.

观看次数

Backbone 中的视图与特定的 DOM 元素相关联(这就是 el 属性的用途).

如果在初始化视图时,它有一个 el 属性,则 Backbone.js 使它成为新视图实例的一个属性.否则,它会查找tagNameidclassName 属性,创建相应的DOM 对象,并将其分配给el 属性.(在 中有解释.)如果甚至没有tagName,然后

元素默认创建.

所以,你可以猜到为什么 TodoViewAppView 使用不同的方法.#todoapp 元素最初存在于 HTML 中的页面上,因此 AppView 可以直接使用它.但是当一个待办事项的视图被创建时,还没有它的 DOM 元素;所以开发者在 Backbone 类上定义了 tagName 来自动创建一个列表项.(在 initialize() 方法中手动完成并不难,但 Backbone 为您节省了一些时间.)

通常视图分为两类之一:模型实例的视图和集合的视图.Backbone 不会强制它,但它建议这可能是您想要的:如果您使用 collectionmodel 实例化视图 选项,它们成为新创建的视图实例的属性,因此您可以通过 view.collectionview.model 访问它们.(例如,如果您使用 foo 选项实例化视图,它将被放入 view.options.foo.)

依赖项

良好做法

这只是我的看法.

  • 依赖越少越好.

  • 遵循 MVC 模式有很多优点.

    请注意,Backbone.js 术语与 MVC 的经典术语不匹配.这是正常的,MVC != 一组类,其定义略有不同.它更像是你应该在脑海中留下的理想"(引自 什么是MVC,它有什么优点?).

<前>MVC |Backbone.js |它能做什么控制器 |查看(大部分) |处理用户交互查看 |由视图渲染的模板 |显示数据型号 |模型与收藏 |代表数据,处理数据访问

  • 模型层通常不应该依赖任何东西.在 MVC 中,模型是您访问数据的地方.例如,这与这些数据的呈现无关.

    在 Backbone 中,模型可以是某个集合的一部分,但这并不是一个严重的依赖项(AFAIK,它只是帮助自动找出与此模型对应的 API 端点的 URL.)

  • 在 Backbone 中,一个集合可能会分配一个相应的模型类,但这也不是必需的.

  • 在 Backbone 中,路由器通常依赖于更高级别的视图(例如整个页面或页面部分的视图),以响应应用程序状态的变化来呈现它们.反过来,这些视图依赖于一些较低级别的视图,例如小部件/页面部分.这些视图可以依赖于集合和其他更底层的视图.反过来,这些可能取决于特定的模型实例.

例如(箭头表示取决于"类型的关系):

<前>+------------+ +--------------+ +------------+状态 |MainRouter |数据:|ItemCollection ||项目模型 |控制:|-------------||---------------||------------||||/api/items +-->|/api/items/*|||||||||||||+---+-+-------+ +--------------+ +------------+|+----------------+ ^ ^v v ||+------------+ +------------+ ||页面级 |关于视图 ||应用视图 |||意见:|-------------||-------------||||部分 ||部分 ||||角色=主要"||角色=主要"|||+--+-+--------+ +--+-+-+------+ |||+---------------|-|-|----+ |||+-----------+ |+----|---------+ ||v v v v v ||+--------------+ +--------------+ +---+-----------+ |小工具 |侧边栏视图 ||页眉视图 ||项目列表视图 ||意见:|--------------||--------------||---------------|||一边||标题||ul ||||||||||||||||+--------------+ +--------------+ +-----------+---+ |||v |+--------+---+|ItemAsLiView||------------||李|||+------------+

请注意,您可以设置多个路由器,在这种情况下,情况可能会有所不同.

todos.js

在 Todos 示例中,开发人员决定 Todo 模型实例应该依赖于相应的 TodoView 实例.当 TodoView 被实例化时,它会在相应的模型实例上创建一个属性 view 并将自己分配给它.以便它可以被 some_todo_model.view 访问.但是,需要注意的是,model.view 只使用一次——在Todo 模型的clear() 方法中,当删除视图实例时模型被清除.

我认为那个没有必要特别依赖.不过,对于这么小的应用来说,或许还可以.

我在视图中找不到任何访问 this.model.view 的示例,因此我无法对此发表评论.

另见

  • Julien Guimont 的回答——几乎所有的答案都是关于 Backbone.js,我认为这是一个很好的信息来源.

I'm a bit confused w.r.t. the structural dependencies when designing your MVC - so we have a Model, Collection and View (I'm not using controllers as yet, but the question applies to it too). Now who has a reference of whom to speak in OO terms. So the collection is a list of models so we can think of it as a one to many dependency from collection to model. In some of the example codes I sometimes see some reference to a view in the 'model' object and the reference of the model in the view. Sometimes a collection in the view.

In the model I sometimes see a this.view and in the view I see something like this.model.view or a this.model and thus the confusion to clarify :)

So what is the 'right' set of dependencies (if there is "a" right way that is) or can everyone be dependent on everyone (don't think that is correct) I.e., who should ideally be dependent on whom in Backbone's MVC design of objects? It's just a bit confusing to know how should they be structurally related when I see such disparate examples - from a noob point of view :) As a noob what is the 'right' way to start structuring my dependencies - once I'm up the learning curve I'd probably figure it out myself, but to start with, how should one go about it? A UML-like diagram would be an added bonus ;)

Another question: Sometimes I see two views in the same piece of code: Eg: the famous todo.js http://documentcloud.github.com/backbone/docs/todos.html

Now although I understand the need of multiple views, what is confusing is how are they different? I mean what's the difference between an 'el' and 'tagName' and how does the view behave differently if either one of them is absent? I mean in the link above one view uses 'tagName' and the other 'el' and I'm not really sure how they correlate (if at all).

I've gone through the documentation intensively, but as I said I'm still learning so I may just not understand parts of it clearly even with all the resources in place and may need some human intervention :)

解决方案

Since Backbone.js is not a framework as such, there's no single "right" way to do anything. However, there are some hints in the implementation that help you to get the idea. Also, there are some general time-tested code organization practices which you can apply. But I'll explain the views first.

Views

Views in Backbone are tied to particular DOM elements (that's what the el property is for).

If, when the view is initialized, it has an el attribute, then Backbone.js makes it a property of the new view instance. Otherwise it looks for tagName, id, and className attributes, creates the corresponding DOM object, and assigns it to the el property of the new view instance anyway. (It's explained in the source.) If there's even no tagName, then <div> element is created by default.

So, you can guess why TodoView and AppView use different approaches. The #todoapp element exists initially on the page in the HTML, so AppView can just use it. But when a view for a todo item is created, there's no DOM element for it yet; so the developer has tagName defined on the class for Backbone to create a list item automatically. (It wouldn't be hard to do by hand in the initialize() method, but Backbone saves some time by doing it for you.)

Usually a view falls into one of two categories: views for model instances, and views for collections. Backbone doesn't force it, but it suggests that it's probably what you want: if you instantiate the view with collection or model options, they become properties of the newly created view instance, so you can access them via view.collection or view.model. (If you, for example, instantiate the view with foo option, it will be put into view.options.foo.)

Dependencies

Good practices

This is just my opinion.

  • Less dependency is better.

  • Following the MVC pattern has a lot of advantages.

    Note that Backbone.js terminology does not match MVC's classical one. That's normal, MVC != a set of classes, and its definitions vary a bit. It's more of ‘an ideal that you should have in the back of your mind’ (quoted from What is MVC and what are the advantages of it?).

MVC        | Backbone.js                 | What it does
Controller | View (mostly)               | Handles user interaction
View       | template rendered by a view | Displays the data
Model      | Model & Collection          | Represents the data, handles data access

  • The model layer should not normally depend on anything. In MVC, model is where you access your data. That has nothing to do with, say, the presentation of this data.

    In Backbone, a model can be a part of some collection, but that's not a heavy dependency (AFAIK, it just helps to automatically figure out URLs of API endpoints corresponding to this model.)

  • In Backbone, a collection may have a corresponding model class assigned, but that's also not necessary.

  • In Backbone, a router usually depends on higher-level views (like views for entire pages or sections of the page), to render them in response to a change in application's state. These views, in turn, depend on some lower-level views, like widgets / page sections. These views can depend on collections and other, even more low-level views. These, in turn, can depend on particular model instances.

As an example (arrows denote "depends on" type of relationship):

           +-------------+              +---------------+   +------------+
State      |MainRouter   |       Data:  |ItemCollection |   |ItemModel   |
Control:   |-------------|              |---------------|   |------------|
           |             |              |/api/items     +-->|/api/items/*|
           |             |              |               |   |            |
           |             |              |               |   |            |
           +---+-+-------+              +---------------+   +------------+
               | +----------------+                  ^              ^
               v                  v                  |              |
           +-------------+   +-------------+         |              |
Page-level |AboutView    |   |AppView      |         |              |
views:     |-------------|   |-------------|         |              |
           | section     |   | section     |         |              |
           | role="main" |   | role="main" |         |              |
           +--+-+--------+   +--+-+-+------+         |              |
              | +---------------|-|-|----+           |              |
              |      +----------+ | +----|---------+ |              |
              v      v            v      v         v |              |
           +--------------+   +--------------+   +---+-----------+  |
Widget     |SidebarView   |   |HeaderView    |   |ItemListView   |  |
views:     |--------------|   |--------------|   |---------------|  |
           | aside        |   | header       |   | ul            |  |
           |              |   |              |   |               |  |
           |              |   |              |   |               |  |
           +--------------+   +--------------+   +-----------+---+  |
                                                             |      |
                                                             v      |
                                                           +--------+---+
                                                           |ItemAsLiView|
                                                           |------------|
                                                           | li         |
                                                           |            |
                                                           +------------+

Note that you can have multiple routers set up, in which case things may look a bit differently.

todos.js

In the Todos example, the developer decided that Todo model instances should depend on corresponding TodoView instances. When TodoView is instantiated, it creates on the corresponding model instance a property view and assigns itself to it. So that it could be accessed by some_todo_model.view. However, it should be noted that model.view is only used once—in Todo model's clear() method, to remove the view instance when the model is cleared.

I think that particular dependency isn't necessary. However, for such a small application, it may be okay.

I couldn't find any example of accessing this.model.view in the view, so I can't comment on this.

See also

这篇关于了解 Backbone.js 中 MVC 的内部结构依赖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆