理解Backbone.js中MVC的内部结构依赖性

PhD*_*PhD 35 javascript backbone.js

在设计MVC时,我对结构依赖性有点困惑 - 所以我们有一个模型,集合和视图(我还没有使用控制器,但问题也适用于它).现在谁有参考谁可以用OO术语发言.因此,集合是一个模型列表,因此我们可以将其视为从集合到模型的一对多依赖.在一些示例代码中,我有时会看到对"模型"对象中的视图的引用以及视图中模型的引用.有时在视图中的集合.

在模型中我有时会看到一个this.view和在视图中我看到的东西像this.model.view或一个this.model因此混淆澄清:)

那么什么是"正确"的依赖关系(如果有"正确的方式")或者每个人都可以依赖于每个人(不要认为这是正确的)即,谁应该理想地依赖于Backbone的MVC中的谁物体的设计?当我看到这些截然不同的例子时,从结果的角度来看,知道他们应该如何在结构上相关,这有点令人困惑:)作为一个菜鸟什么是开始构建我的依赖关系的"正确"方式 - 一旦我上升了学习曲线我可能会自己弄清楚,但首先,应该怎么做呢?一个类似UML的图表将是一个额外的奖励;)

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

现在虽然我理解需要多个视图,但令人困惑的是它们有何不同?我的意思是'el'和'tagName'之间的区别是什么?如果其中任何一个缺席,视图的行为会有何不同?我的意思是在上面的链接中,一个视图使用'tagName'而另一个'el',我不确定它们是如何关联的(如果有的话).

我已经仔细阅读了文档,但正如我所说的那样,我仍然在学习,所以即使有了所有资源,我可能也不会清楚地理解它的一部分,可能需要一些人为干预:)

Ant*_*off 86

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

查看

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

如果在初始化视图时,它具有el属性,则Backbone.js使其成为新视图实例的属性.否则,它会查找tagName,idclassName属性,创建相应的DOM对象,并将其分配给el反正新的视图实例的属性.(它在源代码中有解释.)如果甚至没有tagName,那么<div>默认情况下会创建元素.

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

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

依赖

好的做法

这只是我的看法.

  • 减少依赖性更好.

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

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

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
  • 模型层通常不应该依赖任何东西.在MVC中,model是您访问数据的地方.这与这些数据的呈现无关.

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

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

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

作为一个例子(箭头表示"取决于"关系类型):

           +-------------+              +---------------+   +------------+
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         |
                                                           |            |
                                                           +------------+

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

todos.js

在Todos示例中,开发人员决定Todo模型实例应该依赖于相应的TodoView实例.当TodoView实例化时,对相应的模型实例创建一个属性view,并将自己指定给它.这样它就可以被访问了some_todo_model.view.但是,应该注意的model.view是,只有在Todo模型的clear()方法中使用,才能在清除模型时删除视图实例.

我觉得特别的相关性是没有必要的.但是,对于这么小的应用程序,它可能没问题.

this.model.view在视图中找不到任何访问的例子,所以我不能对此发表评论.

也可以看看

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

  • @Anton:`this.model.view`可以在`TodoView`的初始化方法中找到 - >`initialize:function(){_.bindAll(this,'render','close'); this.model.bind('change',this.render); this.model.view = this; }` (2认同)