在阅读了Ember的页面上的Getting Started指南之后,我仍然有点混淆了什么是反向关系,以及何时定义它们。我知道你可能需要在定义相同类型的多个关系时使用它们,但我发现这个例子非常不清楚。这是来自文档的示例:
var belongsTo = DS.belongsTo,
hasMany = DS.hasMany;
App.Comment = DS.Model.extend({
onePost: belongsTo('post'),
twoPost: belongsTo('post'),
redPost: belongsTo('post'),
bluePost: belongsTo('post')
});
App.Post = DS.Model.extend({
comments: hasMany('comment', {
inverse: 'redPost'
})
});
在这个例子中,为什么redPost
被选为反向而不是其他类型的帖子?如何将redPost
定义为反差,将其与其余部分区分开来?我也真的不明白为什么评论会有多个帖子,只会增加我的困惑。
答案 0 :(得分:66)
首先,this帖子可能会解释一些事情。这不是你的确切问题,但答案的原因是相似的。
但是,为了清楚地了解反转是什么,你应该熟悉directed graphs。虽然不是很明显,但有针对性的图表正在推动belongsTo
和hasMany
背后的理念。
但让我们回到具体细节。让我们以他们为榜样,只消除一些东西,使其更加真实。
App.Post = DS.Model.extend({
comments: DS.hasMany('comment', { inverse: 'post' })
});
App.Comment = DS.Model.extend({
post: DS.belongsTo('post', { inverse: 'comments' })
});
这是一个更真实的例子。每个帖子可以有任意数量的评论,而评论必须属于一个帖子。说得通。如您所见,这些反转是相互引用的。但是反过来又是什么呢?反向关系仅描述了在另一侧调用两个节点之间的边缘。例如,看看这张图片:
您将看到两个节点之间有一条边。从Post
对象的角度来看,边缘称为comments
。如果您希望通过该边缘连接节点,可以调用post.get('comments')
。但是从Comment
对象的角度来看,边缘被称为post
。如果您想使用Comment
对象通过该边缘连接节点,则必须调用comment.get('post')
。这是反过来的。它描述了不同对象如何引用相同的关系。不同的名字,相同的边缘。通过明确声明反向,您可以告诉一个对象其他对象调用边缘的内容。
为什么这很重要?好吧,Ember-Data需要知道这样才能回报关系。例如,假设您有以下代码:
var post = store.find('post', '1');
var newComment = store.createRecord('comment', {});
...
post.get('comments').addObject(newComment);
您所做的是创建新评论并将其连接到现有的帖子对象。一个简单的用例。但是有一个问题:你只是告诉帖子有关评论,反之亦然。你告诉帖子你已经连接了评论,但你没有告诉评论你把它连接到帖子。但作为用户,您希望这两者同时发生。嗯,他们这样做,那是因为Ember-Data为你做到了。使用反向关系的名称,Ember-Data确保当您执行一个时,另一个也会发生。当你这样做时:
post.get('comments').addObject(newComment);
在幕后,Ember-Data真的这样做了:
post.get('comments').addObject(newComment);
newComment.set('post', post);
那是Ember-Data需要反向关系的原因:所以它可以保持完整性,而不必担心它。