backbone.js和不在模型中的状态

时间:2012-08-22 16:42:10

标签: javascript backbone.js

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

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

处理此类应用程序状态的好方法是什么?使用普通的非骨干状态意味着视图/路由器无法监听此状态的变化,因此很难在数据驱动的范例中进行编码。

2 个答案:

答案 0 :(得分:2)

您的按钮过滤器示例可以使用模型事件正确解决。

我认为您的按钮处理程序可以访问任务集合。然后通过选定的模型过滤集合并触发事件,如:

model.trigger( "filter:selected" )

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

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

这是遵循您的要求,尊重不使用或“不持久的属性”,如选择,但我没有任何创伤甚至使用特殊属性如果他们不应该坚持不懈。因此,我还建议修改模型的选定属性以表示易失性状态。

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

model.set( "selected", true )

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

答案 1 :(得分: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);

现在你可以拥有火烈鸟触发器并像其他任何东西一样监听事件!

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

我对路由器的操作可能与您的操作不同,但我将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
}

这有帮助吗?