如何处理backbone.js中的关系

jon*_*atr 11 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
Run Code Online (Sandbox Code Playgroud)

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

所以问题是,我应该使用某种全局变量来保存所有事件,用户等等,当我从服务器获取信息时把它放在那里(并在我从服务器上抓取东西之前检查那里),也许在某些一种localstorage(以及如何使用骨干关系?).

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

你推荐什么方式?

谢谢!

jmk*_*142 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
});
Run Code Online (Sandbox Code Playgroud)

当您创建Backbone关系模型时,它会自动为您创建一个以您指定的'key'命名的子模型集合.因此,您拥有的每个用户都会拥有自己的相关事件集合.

基本上,当您创建或获取用户时,您可以为其提供所需的相关模型的引用.因此,例如,您的用户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
});
Run Code Online (Sandbox Code Playgroud)

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

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

等等.

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

例如,您创建User模型的新实例.

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

根据您的关系需求,这似乎是一个很好的选择.

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

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

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


Mos*_*man 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
Run Code Online (Sandbox Code Playgroud)

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

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

最后,我将始终向人们指出 Require.js 与 Backbone 的结合。无耻地参考我今天给出的一个答案,看看吧,无论如何它都会让生活变得更轻松: Backbone Design