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

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

所以问题是,我是否应该使用某种全局变量来保存所有事件、用户等,当我从服务器获取信息时将其放在那里(并在我从服务器获取某些东西之前检查那里),也许在某些某种本地存储(以及如何使用骨干关系来做到这一点?)。

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

你推荐什么方法?

谢谢!

4

2 回答 2

18

就像@mu_is_too_short 评论的那样,骨干关系可能是您有兴趣研究的东​​西。使用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
});

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

基本上,当你创建或获取用户时,你给它提供了它需要的相关模型的引用。例如,您的用户 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
});

等等等等。

这是产生一对一、一对多和反向关系的好方法。这很关键。当您定义模型之间的关系并创建模型时。

例如,您创建一个用户模型的新实例。

骨干关系自动创建反向链接(事件模型具有由反向关系键“belongsToUser”(或您命名的任何名称)定义的属性。这使得上下遍历模型/子模型层次结构非常方便。

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

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

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

更新:骨干关系现在支持 require.js,从 2014 年 4 月 1 日的 0.8.8 版开始 - 感谢 Kenneth

于 2012-06-04T01:29:59.097 回答
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

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

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

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

于 2012-06-03T19:43:09.157 回答