2

我正在 Backbone 中处理一个示例 ToDo 列表项目,我想了解框架希望我如何在嵌套列表场景中组织其视图和模型。

为了澄清我的意思,我的单页 Backbone 应用程序应该显示待办事项列表。从后端的角度来看,有一个 List 资源和一个 Item(待办事项列表中的单个条目)资源。类似于以下内容:

  • 周一的家务
    • 拿起邮件
    • 洗衣服
    • 拿起干洗
  • 购物清单
    • 芹菜
    • 牛肉
    • 你明白了……

因为我的是一个 Rails 3.2 应用程序,所以我模糊地遵循 Railscasts Backbone.js 教程,所以这就是我从中获得当前设计的地方。我很想知道我是否完全偏离了 Backbone 规定的模式,或者我是否走在正确的轨道上!

到目前为止,我有:

ListsIndex View                         //index of all lists
\-- ListsCollection
     \-- ListView / Model               //individual list
          \-- ItemsIndex View           //index of items in one list
              \-- ItemsCollection
                  \-- Item View / Model //individual todo item

流程将是:

  1. 在路由器初始化时,/lists 后端路由上的 fetch() 列表集合。在 ListsIndex 的集合部分的“重置”事件上,对集合中的每个项目执行 render(),附加到列表索引视图模板。
  2. 在每个项目视图的初始化方法中(这是您连接第二级提取的地方吗?) fetch() 从 /lists/:id/items 后端路由到特定于该视图的 ItemsCollection 中的项目。
  3. 在同一方法中,实例化一个 ItemsIndex 对象并将集合传递给它。再一次,在 ItemsIndex 中,有一个“重置”事件处理程序,用于填充集合时,它应该呈现从项目集合中获取的每个模型并将它们附加到自己的视图中。

我实质上是在采用 List 的设计并将其镜像到其项目的一个级别。不同之处在于我不再需要依赖路由器。因此,我使用 ListView 的初始化方法来达到类似的效果。

是/不是?超级错?谢谢!

4

1 回答 1

3

TL:博士;1)我会引导你的初始数据而不是 fetch() reset()。2)您可以根据需要在视图的初始化中进行获取。或者您可以在开始时加载数据。请记住,如果您在 init 中获取,异步性质不会在渲染时准备好数据。如果您有一个监听器在等待同步/添加/等,这不是问题。3) 我不知道您所说的 itemIndex 对象是什么意思,但您可以创建对象并根据需要向它们添加集合。或者,如果您知道所有列表最终都会有一个集合,则可以在开始时进行烘焙。您可以根据需要重置(除非您给它选项{add:true},否则自动获取)或者只是在它们进入时将它们一一添加,尽管reset(),删除先前的视图,渲染所有视图似乎是人们使用完整的 fetch() 做事的常用方式。

我觉得它看起来很不错。Backbone 的好处是您可以通过多种不同的方式进行操作。例如,您的 2 号表示要从视图中连接第二个 fetch()。如果你想延迟加载,你可以这样做。或者您可以在应用程序启动时获取所有数据,然后再完成任何操作。这真的取决于你。我可能会这样做。

这就是我可能制作这样一个应用程序的方式(只是我的偏好,我不知道它是更好或更坏,或者它是否与您描述的相同。)

首先,我将创建一个名为 ListModel 的模型。它将有一个 id 和一个名称 attr。这样,您可以创建许多单独的列表,每个列表都有自己的 id,您可以单独获取。

每个 ListModel 内部都有一个 ItemsCollection。这个集合有一个基于它所属的 ListModel 的 url。因此,ListModel-1 的集合 url 类似于 /list/1

最后你有 ItemModel ,它是一个资源 id 和文本。

ListCollection
    ListModel  // Monday Chores
        ItemCollection
            ItemModel  // Mail
            ItemModel  // Laundry
            ItemModel  // Drycleaning
    ListModel  // Grocery
        ItemCollection
            ItemModel  // Celery
            ItemModel  // Beef

所以在这个小展示中,你会注意到我还没有对视图做任何事情。我不知道它是否更像是一个概念性的东西,但这就是数据层次结构的样子,你的视图应该完全独立于它。我不确定你是如何包含上面的视图的,但我认为这可能会让它更清楚。

至于定义这些结构,我认为有两点。

首先,我会确保我的 ListModel 已在我的集合中定义。这样,我可以在生成/添加新模型时使用集合 add(hash) 来实例化它们。

其次,我将定义 ListModel,以便在创建时自动创建一个 ItemCollection 作为该 ListModel 对象的属性(而不是作为属性)。

所以理想情况下,您的 ListModels 应该是这样的:

ListModel.ItemCollection

在应用程序初始化之前,我会引导数据而不是 fetch()。(这种地址是您创建的第 1 点)理想情况下,当您的 Backbone 应用程序启动时,它应该从一开始就拥有所需的所有必要数据。我会在头脑中传递一些这样的数据:

 var lists = [listModel-1-hash, listModel-2-hash];

现在,当应用程序启动时,您可以立即创建这两个列表。

var myLists = new ListCollection();

_.each(lists, function(hash) {
    myLists.add(hash);  // Assumes you have defined your model in the ListCollection
}

现在,您的 List Collection 拥有它需要的所有列表模型。

这是视图的来源。您可以将任何内容传递给任何视图。但我可能会将观点分解为三件事。

AppView、ListModelView、ItemModelView 就是这样。

想象一下这样的结构:

<body> // AppView
    <ul class="List"> // ListModelView
        <li class="Item"></li>     // ItemModelView
    </ul>
    <ul class="List"> // ListModelView
    </ul>
</body>

当您启动您的应用程序并创建一个 AppView 时,您将在 AppView 内生成每个 ListModelView 并将其附加到正文中。我们的清单是空的。也许当您单击它时,它会延迟加载项目。这就是你连接它的方式。

// In ListModelView
events: {'click':'fetchItems'}

fetchItems: function() {
    this.model.itemCollection.fetch();  // Assumes you passed in the ListModel into view
}

因此,由于我从一开始就引导数据,因此该 fetch() 调用将是您的“第二次”获取。(我正在解决您提出的第 2 点。)您可以在初始化时获取它。请记住,它是一个异步函数,因此如果您在渲染时需要它们,它将无法工作。但是,您可以做的是向此视图添加事件侦听器,这些侦听器正在侦听向您的 itemCollections 添加事件。

this.model.itemCollection.on('add', this.addItemView, this);

addItemView()将生成 itemViews 的新实例并附加它们。

至于第 3 点,您可以在需要时实例化一个集合并将其放入您的 ListModel。或者你可以像我一样做,确保你所有的模型总是有一个 ItemCollection。这取决于您的偏好和目标。您可能不需要所有这些,但出于某种原因,我想说明一下。我不知道,也许它有帮助。

于 2012-08-22T11:01:42.967 回答