如何在backbone.js中处理关系

11

在设计我的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
好的,我的想法是在用户加载页面时加载事件列表,当用户单击事件时加载有关该事件的其他信息(评论、参与和用户)。

所以问题是,我应该使用某种全局变量来保存所有事件、用户等等的信息,并在从服务器获取信息之前将其放在那里(并在从服务器获取信息之前检查那里),也许在一些本地存储中(如何使用backbone-relational进行此操作?)。

另一个想法是让每个事件拥有自己独立的数据,但这样做的问题是每次单击事件时可能会发送冗余数据。

你推荐哪种方式呢?

谢谢!

2个回答

18

正如@mu_is_too_short所评论的那样,Backbone-relational可能是您有兴趣了解的内容。使用Backbone-relational,您的模型和子模型集合会自动创建,并且可以跨父子关系管理事件。

我将为您提供一些示例代码,以便您可以尝试一下。 您的示例代码可能如下所示。

User有多个Events:

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-relational模型时,它会自动为你创建一个子模型的集合,集合的名称由您指定的“键”命名。所以你拥有的每个用户都将拥有其自己的相关事件集合。
基本上,当你创建或获取用户时,你要为它提供它需要的相关模型的引用。例如,你的用户id=1可能需要Event 5、7和11。只要这些引用以数组形式定义,就可以使用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
});
这是一种很好的方式来创建一对一、一对多和反向关系。这很重要。当你定义模型之间的关系并创建一个模型时,Backbone-relational会自动创建反向链接(例如,Event模型具有一个由反向关系键“belongsToUser”(或任何你命名的键)定义的属性)。这使得在模型/子模型层次结构中向上和向下遍历非常方便。
根据你的关系需求,这似乎是一个很好的选择。
如果你想要多对多的关系,有一种绕路的方法(使用中间模型),但我发现这种方法有点奇怪,所以我避免使用它。Paul-Uithol一直在更新Backbone-Relational,并不断添加新功能。学习曲线一开始可能有些难,但一旦你开始习惯它,它就非常方便。
注意:强调一下,Mosselman推荐使用Require.js,我也非常赞同。它使我的代码更易管理。你可以修改Backbone-relational代码使其符合AMD,并且它能够无缝地与Require一起使用。
更新:backbone-relational现在支持require.js,版本为2014年4月1日的0.8.8版-感谢Kenneth。

通过事件模型,是否可以将事件与用户关联起来?类似这样的方式:myUser.set('events', [myEvent1, myEvent2, myEvent3]);?还是必须通过相关模型的ID引用关系? - Jake Wilson
1
@orangewarp 在2014年4月1日的0.8.8版本中,backbone-relational现已支持require.js。请访问http://backbonerelational.org/#change-log。 - Kenneth

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接