2

在 Backbone 的数据驱动范式中,主干视图/路由器应该订阅模型更改并根据模型更改事件采取行动。遵循这个原则,应用程序的视图/路由器可以相互隔离,这很好。

但是,模型中没有持久化的应用程序的状态有很多变化。例如,在待办事项应用程序中,可能有一些按钮可以让您查看“已完成”、“未完成”或“全部”的任务。这是模型中未保留的应用程序状态。请注意,任何任务的完成状态都是持久的,但视图中的当前过滤器是瞬态状态。

处理这种应用程序状态的好方法是什么?使用普通的、非主干状态意味着视图/路由器无法监听此状态的变化,因此在数据驱动范式中变得难以编码。

4

2 回答 2

2

您的按钮过滤器示例可以使用Model events正确解决。

我想您的按钮处理程序可以访问任务 Collection然后过滤所选模型上的集合和触发事件,例如:

model.trigger( "filter:selected" )

或者

model.trigger( "filter:un-selected" )

ModelView可以在其模型上监听这些事件并采取相应的行动。

这是遵循您尊重未使用或“不持久的属性”的要求,例如选择但我没有任何创伤来使用特殊属性,即使它们不应该是持久的。因此,我还建议修改模型的selected属性以表示易变状态。

因此,在您的按钮处理程序中过滤集合并修改模型中的选定属性是我的首选解决方案:

model.set( "selected", true )

您始终可以覆盖Model.toJSON()之前进行清理,或者只是将此特殊属性sync保留到您的服务器并在那里被忽略。

于 2012-08-22T16:55:27.300 回答
0

评论很长,所以我会产生第二个答案来比较。

首先,我觉得“已完成”、“未完成”完全是可以保留的项目模型属性。或者,如果您的项目由许多用户拥有,每个用户都有自己的“已完成”“未完成”状态,那么该项目将有一个 completedState 子模型或其他东西。重点是,虽然@fguillen 为您提供了两种可能的解决方案,但我也更喜欢他的第二种方式,让模型包含属性和按钮/视图来完成大部分工作。

对我来说,模型为此拥有自己的自定义事件是没有意义的。在我看来,过滤器按钮只需要处理提供适当的视图。(要显示哪些项目)因此,我只会让按钮元素调用一个函数,该函数或多或少地直接在集合上运行过滤器。

event: {
    'click filterBtnCompleted':'showCompleted'
},
showCompleted: function(event) {
    var completedAry = this.itemCollection.filter(function(item) {
        return item.get('completed');
    });

    // Code empties your current item views and re-renders them with just filtered models
}

我倾向于将这些便利的过滤器函数隐藏在集合中,这样我就可以调用:

this.ItemCollection.getCompleted(); // etc.

将这些属性留在模型中并在服务器上忽略它们很好。尽管如此,在我看来,它们确实是你想要坚持的属性。

还有一件事,您说使用普通的非主干状态会牺牲事件。(咧嘴笑:-)不是这样!您可以轻松扩展任何对象以具有 Backbone.Event 功能。

var flamingo = {};

_.extend(flamingo, Backbone.Events);

现在您可以拥有 flamingo 触发器并像其他任何事情一样监听事件!

编辑:解决路由器>查看数据交易-------------------//

我对路由器所做的可能不是您所做的,但我将 appView 作为选项传递给路由器。我在 appView 中有一个名为 showView() 的函数,它创建子视图。因此,我的路由器可以直接访问我正在处理的视图。

// Router
initialize: function(options) {
    this.appView = options.appView;
}

在我们的例子中,可能需要过滤 itemsView 以显示已完成的项目。注意:我还有一个管理子视图的 showView() 函数。您可能只是在您的场景中直接使用 appView。

所以当像 /items/#completed 这样的路由被调用时,我可能会做这样的事情。

routes: {
    'completed':'completed'
},
completed: {
    var itemsView = ItemCollectionView.create({
        'collection': // Your collection however you do it
    });
    this.appView.showView(itemsView);

    itemsView.showCompleted(); // Calls the showCompleted() from View example way above
}

这有帮助吗?

于 2012-08-22T18:29:56.623 回答