backbone.js和模型中没有的状态

backbone.js and states that are not in models

本文关键字:状态 js 模型 backbone      更新时间:2023-09-26

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

然而,应用程序的状态有很多变化,这些变化并没有在模型中持久化。例如,在待办事项应用程序中,可以有一些按钮让你查看"已完成"、"未完成"或"全部"的任务。这是一个未在模型中持久化的应用程序状态。请注意,任何任务的完成状态都是持久的,但视图中的当前筛选器是瞬态。

处理这种应用程序状态的好方法是什么?使用一个简单的、无主干的状态意味着视图/路由器无法监听这种状态下的变化,因此很难在数据驱动的范式中进行编码。

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

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

model.trigger( "filter:selected" )

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

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

这遵循了您的要求,即尊重不使用或"不持久的属性",如所选的,但我对使用特殊属性没有任何创伤,即使它们不应该持久。因此,我还建议修改Models的selected属性,以表示易失性状态。

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

model.set( "selected", true )

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

Comment变长了,所以我将生成第二个答案进行比较。

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

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

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
}

这有帮助吗?