Backbone:同一模型的多个视图模型
Posted
技术标签:
【中文标题】Backbone:同一模型的多个视图模型【英文标题】:Backbone: multiple View Models for the same model 【发布时间】:2012-01-25 17:33:30 【问题描述】:新手主干问题:
上下文:建立一个有骨干的购物清单
我有一个带有名称、描述和标签(数组)属性的模型类。 我想基于这个模型或这个模型的集合创建两个视图。
第一个视图将显示所有项目,如下所示:
<ul>
<li><h3>Item 1 Name</h3>
<p>Item 1 Description</p>
<p>Tag1, Tag2 ,Tag3</p>
</li>
.......
</ul>
第二个视图将显示标签列表和标记项目的数量,如下所示:
<ul>
<li>Tag1<span>count of items tagged with tag1</span></li>
<li>Tag2<span>count of items tagged with tag2</span></li>
<li>Tag3<span>count of items tagged with tag3</span></li>
</ul>
我构建了模型、集合和视图来支持第一个视图。我想知道使用现有模型(或创建新模型?)构建第二个视图的正确方法。
提前谢谢...
现有的 Item 模型和集合(从 Todo.js 示例中提取)
window.Item = Backbone.Model.extend(
// Default attributes for a todo item.
defaults: function()
return
order: Items.nextOrder()
;
);
window.ItemList = Backbone.Collection.extend(
model: Item,
localStorage: new Store("items"),
nextOrder: function()
if (!this.length) return 1;
return this.last().get('order') + 1;
,
comparator: function(item)
return item.get('order');
);
更新:尽管在显示带有项目计数的标签名称时覆盖 parse() 方法有效,但在添加新项目后我无法刷新标签名称/项目计数列表。这可能是由于视图是从不同的集合呈现的。我将尝试扩展 ItemList 集合并覆盖 parse() 方法。非常感谢任何帮助。
【问题讨论】:
【参考方案1】:@machineghost 是正确的;模型与视图完全分离,因此您可以根据需要将任意数量的视图附加到同一模型。如果视图具有您想要共享的逻辑或属性,您还可以扩展视图。当我使用 Backbone 时,我经常发现自己扩展父视图只是为了覆盖 render
函数,或者提供不同的模板。
第一次查看
ShoppingCartView = Backbone.View.extend(
model: ShoppingCart
...
);
第二个独立视图
CheckoutView = Backbone.View.extend(
model: ShoppingCart
...
);
第二个视图先扩展
CheckoutView = ShoppingCartView.extend(
template: a_different_template // syntax depends on your templating framework
...
);
【讨论】:
感谢您的信息。更多背景信息:我已经使用 localStorage 示例修改了 Todo.js 以满足我的需要。目前,item 以这种格式存储在 localStorage 中:name: "Item1", description: "Item1 Desc", tags: ["Tag1", "Tag2", "Tag3"]。因此, fetch() 调用以这种格式检索。我想将此格式转换(映射)为 tagName:“Tag1”,tagCount:“3”。我相信我可以用下划线的 map 方法做到这一点。但是,我不清楚我应该把那段代码放在哪里。【参考方案2】:我自己对 Backbone.js 还很陌生,所以对这个答案持保留态度,但我认为......你只是提出了第二个观点。解耦模型和视图的全部意义在于,如果您只想对视图做一些不同的事情,您就不需要对模型做任何事情。
所以,我认为您只需要创建 YourView2,告诉它使用与 YourView1 相同的模型,然后您就可以开展业务了。
【讨论】:
你不认为第二个视图需要它自己的模型吗?这不像我在显示具有稍微不同模板的相同模型。我需要按标签名称获取项目数量。理想情况下,第二个视图将使用这样的模型:tagName:"Tag1", tagCount:"4" 我不清楚为什么需要(甚至鼓励)制作一个单独的模型。您不能只在现有模型中添加一个 tagCount,然后在视图 #2 中重新使用它吗?一般来说(在任何 MVC 范式中),您应该只需要使用一个新模型来表示一个新事物。如果您只想稍微不同地表示旧的东西,您可以修改原始模型(或者,如果您出于某种原因真的不想这样做,例如原始模型已经有一百万行,您总是可以子类化原始模型...)。 我看不出将 tagCount 添加到现有模型会有什么帮助。然后,每个项目都有一个 tagCount 属性。给定一个项目列表,我想显示标签名称和带有该标签的项目数量。有点像 SQL 中的 GROUP BY 子句。 哦,我误会了。在这种情况下,为什么不直接将功能添加到您的集合 (ItemList) 中? 因为我需要在一个页面中显示所有项目,并在另一个页面上按标签名称进行项目计数。【参考方案3】:Backbone.js 谷歌小组的 Paul Yoder 提供了解决方案。 你可以查看here
【讨论】:
【参考方案4】:经过一番研究,我发现Collection.Parse 方法似乎是在 fetch() 操作后转换响应的正确位置。看起来我需要一个新的集合模型、集合和视图对象。这就是我在我的集合对象中实现解析函数的方式。在 Chrome 中测试成功。欢迎提出改进建议
<snip>
parse: function(response)
var items = response; //the raw item model returned from localStorage
var tagNameItemCount = [];
var selectedTags = ["Tag1", "Tag2", "Tag3"];
for(i = 0; i < selectedTags.length; i++)
var currentTagName = selectedTags[i];
var currentItemCount = this.getItemsCountByTagName(currentTagName, items);
tagNameItemCount.push(tagName: currentTagName, tagCount: currentItemCount);
return tagNameItemCount;
,
getItemsCountByTagName: function (tagName, items)
var taggedItems = _.filter(items, function(item) return _.include(item.tags, tagName); );
return taggedItems.length;
,
</snip>
【讨论】:
在创建新的视图/集合并覆盖解析以用于显示目的时,在修改 Items 集合后视图不会刷新。更新了问题以反映此问题。以上是关于Backbone:同一模型的多个视图模型的主要内容,如果未能解决你的问题,请参考以下文章