>我有一个评论列表。这些注释具有一个名为"vote"的属性(用户可以对注释进行投票(,它们最初按投票排序(降序,onRender(。
现在,当用户投票时,评论的顺序会被动更新以反映新的投票。
是否有可能以某种方式保持初始排序顺序不变?我想避免将用户与评论混淆,而她/他在页面上时会自动交换顺序。
有什么好方法可以解决这个问题吗?我在渲染页面时考虑的可能是一次性排序,或者以某种方式保存顺序,然后在响应刷新集合时重新应用它。
您可以使用函数对 Minimongo 查询进行排序。所以像这样:
const initialVotes = new Map();
Comments.find({}, {sort: (a, b) => {
if (!initialVotes.has(a._id)) initialVotes.set(a._id, a.votes);
if (!initialVotes.has(b._id)) initialVotes.set(b._id, b.votes);
return initialVotes.get(b._id) - initialVotes.get(a._id);
});
这将使评论按初始投票排序。如果任何其他更改(例如用户编辑评论(,这将被动传播,如果进行新评论,它将被动添加。但是,如果投票发生变化,顺序不会改变(但可能呈现的投票数仍将更新(。
reactive: false
选项进行非反应性查找,例如:
Comments.find({},{sort: {vote: -1}, reactive: false});
如果您想在原始列表之后附加新评论,那么我会呈现两个评论列表,一个紧接着另一个。首先呈现现有注释的排序列表,然后按创建顺序响应式呈现在初始呈现时间之后创建的注释列表。第二个列表最初是空的,根本不会呈现,但最终新评论将出现在那里,并带有自己的投票计数。
现在,由于上面的光标是非反应性的,我们如何在不更改顺序的情况下让投票计数被动更新?答:(在 Blaze 的情况下(使用反应式助手!
Template.myTemplate.helpers({
currentVote(){
return Comments.findOne(this._id).vote;
}
});
从性能 pov 来看,这实际上非常便宜。
由于您不关心新评论,只关心新投票,我会按照您想要的方式使用 Meteor.call(( 进行初始人口排序,如@sdybskiy所述。 然后我会为这些评论设置订阅以获得投票计数。
在模板的 onCreated(( 中,您可以设置如下订阅:
let voteCursor = Votes.find({commentIds: comments});
voteCursor.observe({
added: function(newDocument, oldDocument) {
// the published vote would have a commentId, so here you
// would go to your client store for the comments, find the
// comment, and increment the count
},
removed: function(oldDocument) {
// same idea here, but process a vote being removed
}
});
请注意,我传入了从该方法返回的所有注释的 ID,因此发布将仅发布这些注释的投票。