是否可以只对集合进行一次排序,然后在反应性的情况下保持该顺序不变



>我有一个评论列表。这些注释具有一个名为"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,因此发布将仅发布这些注释的投票。

相关内容

最新更新