如何处理backbone.js中的关系

时间:2012-06-03 15:01:43

标签: javascript rest backbone.js backbone-relational

我一直坚持如何设计关于我的模型关系的backbone.js应用程序。

如果我有一个事件模型,它有几个关系,比如一个用户模型可以有很多事件,而事件模型又可以有很多注释和参与。用户可以有很多评论,参与可以有一个用户和一个事件。哇,真糟糕!

Event has many Comments
Event has many Participations
Event has one User

User has many Events
User has many Participations
User has many Comments

Comment has one Event
Comment has one User

Participation has one User
Participation has one Event

Okey,所以我的想法是在用户加载页面时加载事件列表,当用户点击事件时加载有关该事件的其余信息(评论,参与和用户)。

所以问题是,我应该使用某种全局变量来保存所有事件,用户等等,当我从服务器获取信息时将其放在那里(并在我从服务器获取内容之前检查那里),也许在某种类型的本地存储中(我如何使用骨干关系?)。

我的另一个想法是让每个事件都有自己独立的数据,问题是我每次点击一个事件时都会发送冗余数据。

您推荐什么方式?

谢谢!

2 个答案:

答案 0 :(得分:18)

与@mu_is_too_short一样,Backbone-relational可能是您有兴趣研究的内容。使用Backbone-relational,您的模型和子模型集合将自动创建,并且可以跨父子关系管理事件。

我只会给你一些示例代码,以便您可以尝试一下。 您的示例代码的一部分可能看起来像这样。

用户有很多活动:

User = Backbone.RelationalModel.extend({
    relations: [
        type: Backbone.HasMany,   // Type of relationship
        key: 'events',            // How we reference the sub-models in collection
        relatedModel: 'Event',    // The sub-model type
        collectionType: 'EventCollection',  // The sub-model collection
        reverseRelation: {
            key: 'belongsToUser'            // Key we use to refer to the parent
        }
    ],
    // Other Backbone.Model properties and functions
});

当您创建Backbone关系模型时,它会自动为您指定一个以您指定的“键”命名的子模型集合。因此,您拥有的每个用户都会将自己的相关事件集合整理好。

基本上,当您创建或获取用户时,您可以为其提供所需的相关模型的引用。因此,例如,您的用户ID = 1可能需要事件5,7和11.(我只是使用ID)。只要这些引用以数组形式定义,那么您可以使用Relational的fetchRelated方法懒惰地加载它们。

myUser = new User();
myUser.set({
    name: 'RayMysterio',
    age: '26',
    events: [5, 7, 11]    // Or this might just come with the User object from your server
});

myUser.fetchRelated('events');
// This will go fetch the related events for this user model from the URL you designate.

myUser.get('events');
// The collection of events are treated like an attribute of the User model.

myUser.get('events').find(function(eventModel){
    return // some find condition - or whatever you want to do on that collection
});

您可能希望将某些侦听器绑定到子模型。

myUser.bind('add:events', function(model, collection) {
    // Whatever code you want to happen when new models are added to the user events coll
});

等。等

这是一种生成一对一,一对多和反向关系的好方法。这非常关键。在模型之间定义关系并创建模型时。

E.g。您创建用户模型的新实例。

Backbone-relational自动创建反向链接(事件模型具有由反向关系键'belongsToUser'定义的属性(或者您命名的任何名称)。这使得在模型/子模型中上下移动非常方便层次结构。

根据您的关系需求,这似乎很合适。

如果你想要多对多,有一种圆润的方式(使用中间模型),但我发现这有点不稳定,我避免它。 Paul-Uithol已经对Backbone-Relational进行了一段时间的更新,并且新功能不断增加。学习曲线起初对我来说有点困难,但是一旦你开始习惯它,它就会非常方便。

注意:为了强调,Mosselman推荐Require.js,我也非常同意这一点。它使我的代码更易于管理。你可以修改(包装)Backbone关系代码,使其符合AMD标准,并且与Require一起完美运行。

更新:骨干关系现在支持2014年4月1日发布的0.8.8版本的require.js - 感谢Kenneth

答案 1 :(得分:0)

理论上,您可以加载所有单独的集合,然后对集合使用本地过滤,以便在渲染时获取相关模型。

当然,您必须考虑安全问题。

至少对我而言,我并不完全清楚你的问题是什么,你要抓住的信息,但我会尽力回答。

我的假设是你有一些带有一些额外数据的事件,你需要显示与此相关的信息。然后你还需要能够做一些事情,比如添加评论等。

正如我所说,你可以考虑做以下事情:

var Events = Backbone.Collection.extend({
    url: '/events', // You might want to let the app return only an account's events or something, not just ALL events.
    initialize: function(){
        this.fetch();
    }
});

var Comments = Backbone.Collection.extend({
    url: '/comments',
    initialize: function(){
        _.bindAll(this, 'getEventComments');
        this.fetch();
    },

    getEventComments: function(event_id){
        return _.filter(this.models, function(model){ return model.get('event_id') == event_id; });
    }
});
//etc

通过使用下划线的滤镜功能,您可以在每次需要时快速获取相关模型(例如渲染时)。

在某种程度上,这与您在服务器端脚本中执行的操作相同。有些数据库会保存所有带有记录的表,因为您的集合将在此处执行,并且您的代码只是根据某些输入向数据库询问相关的数据。

最后,我将始终将Require.js与Backbone结合使用。无耻地提到我今天给出的答案,检查出来,无论如何都会让生活变得更轻松: Backbone Design