是否可以只对一个集合进行一次排序,然后尽管有反应,但仍保持该顺序不变?
Is it possible to sort a collection only once and then keep that order intact despite reactivity?
我有一个评论列表。这些评论有一个名为 "vote" 的属性(用户可以对评论进行投票),它们最初按投票排序(降序,onRender)。
现在,当用户投票时,评论的顺序会被动更新以反映新的投票。
是否有可能以某种方式保持初始排序顺序不变?当 she/he 在页面上时,我想避免将用户与评论自动交换顺序混淆。
请问有什么好的方法可以解决吗?我在考虑渲染页面时可能是一次性排序,或者以某种方式保存顺序,然后在响应式刷新集合时重新应用它。
因为您不关心新评论,只关心新投票,所以我会用 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,因此发布将只发布这些评论的投票。
您可以使用 reactive: false
选项执行 non-reactive find,例如:
Comments.find({},{sort: {vote: -1}, reactive: false});
如果您想在原始列表之后添加新评论,那么我会呈现两个评论列表,一个接一个。首先呈现现有评论的排序列表,然后以创建顺序响应地呈现在初始呈现时间之后创建的评论列表。第二个列表最初是空的,根本不会呈现,但最终新评论会出现在那里,并带有自己的投票数。
现在,由于上面的光标是 non-reactive,我们如何在不改变顺序的情况下让投票计数反应性地更新?答案:(在 Blaze 的情况下)使用反应式助手!
Template.myTemplate.helpers({
currentVote(){
return Comments.findOne(this._id).vote;
}
});
从性能角度来看,这实际上是出奇的便宜。
您可以使用函数对您的 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);
});
这将使评论按初始投票排序。如果有任何其他变化(比如用户编辑评论),那将反应性传播,如果有新评论,它将反应性地添加。但如果票数改变,顺序不会改变(但可能呈现的票数仍会更新)。
我有一个评论列表。这些评论有一个名为 "vote" 的属性(用户可以对评论进行投票),它们最初按投票排序(降序,onRender)。
现在,当用户投票时,评论的顺序会被动更新以反映新的投票。
是否有可能以某种方式保持初始排序顺序不变?当 she/he 在页面上时,我想避免将用户与评论自动交换顺序混淆。
请问有什么好的方法可以解决吗?我在考虑渲染页面时可能是一次性排序,或者以某种方式保存顺序,然后在响应式刷新集合时重新应用它。
因为您不关心新评论,只关心新投票,所以我会用 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,因此发布将只发布这些评论的投票。
您可以使用 reactive: false
选项执行 non-reactive find,例如:
Comments.find({},{sort: {vote: -1}, reactive: false});
如果您想在原始列表之后添加新评论,那么我会呈现两个评论列表,一个接一个。首先呈现现有评论的排序列表,然后以创建顺序响应地呈现在初始呈现时间之后创建的评论列表。第二个列表最初是空的,根本不会呈现,但最终新评论会出现在那里,并带有自己的投票数。
现在,由于上面的光标是 non-reactive,我们如何在不改变顺序的情况下让投票计数反应性地更新?答案:(在 Blaze 的情况下)使用反应式助手!
Template.myTemplate.helpers({
currentVote(){
return Comments.findOne(this._id).vote;
}
});
从性能角度来看,这实际上是出奇的便宜。
您可以使用函数对您的 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);
});
这将使评论按初始投票排序。如果有任何其他变化(比如用户编辑评论),那将反应性传播,如果有新评论,它将反应性地添加。但如果票数改变,顺序不会改变(但可能呈现的票数仍会更新)。