我正在努力解决一个奇怪的问题。只要文档使用某个属性进行更新,它就不再与发布查询匹配。 Meteor将其从DOM中删除并将其从客户端集合中删除。
我需要将列表留在原地,以便用户仍然可以返回并撤消他们的选择。但是我需要它们在下一页加载时不显示。
如果我将整个集合发送到客户端,然后如果返回的结果超过0,则可以模拟我所追求的内容。在刷新时,仅显示尚未选择的列表。显然这不利于表现。
我的发布查询基本上只是过滤掉正确的列表类型并且也会拉出 在用户未选择喜欢/不喜欢的列表中。它增加了限制,但我做不到 它可以在不丢失之前选择的列表的情况下工作
Meteor.publish('listings', function(type, limit, ulid) {
var query, options;
query = {
type: type,
completed: true,
'public': true
};
options = {
sort: {title: 1},
limit: 1000 // debugging, should be param
};
// if user is logged in, get their listing id
if (ulid) {
query.likedBy = { $ne: ulid };
query.dislikedBy = { $ne: ulid };
}
return Listings.find(query, options);
});
// client, simulates the effect I need, but doesn't work if you increase limit
Template.listings.helpers({
listings: function() {
var listType, results;
listType = Session.get('listingType');
results = Listings.find({type: listType }, {reactive: false}).fetch();
// prevents race condition where sometimes listings come through anyway
if (Meteor.user()) {
var ul = Session.get('userListing')._id;
results.likedBy = { $ne: ul };
results.dislikedBy = { $ne: ul };
}
// if results haven't arrived fetch again with reactivity
if (!results.length) {
results = Listings.find({ type: listType }).fetch();
}
// append a 'no listings avail.' card to the end of results
// If no results are found, user only sees not found card
results.push({type: 'empty'});
return results;
}
});
对于视觉,每个文档一次显示一个,用户向右滑动 获取新的列表,然后返回并查看/撤消旧列表。
-----------------------
| |
| |-----------------| |
| | | |
| | | |
| | | |
| | listing #1 | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| |-----------------| |
| |
-----------------------
答案 0 :(得分:3)
这是一个有趣的问题。您并不是真的希望使模板具有反应性和非反应性,而是找到一种方法来保持在用户“会话”期间发布某些文档,即使字段已更改,这通常会导致文档未被发布。< / p>
我想到的一个解决方案是,如果在当前会话期间添加了喜欢或不喜欢的内容,那么可以使用第二个出版物来保存那些已被喜欢或不喜欢的文档。两个出版物可以从同一个集合中发布,结果是客户端上的集合是这两个出版物的联合。
因此,当用户点击“喜欢”或“不喜欢”时,您会将该文档的_id添加到会话变量中,该变量是要保留发布的文档数组。使用deps.autorun中的订阅,您可以将此_id列表反应性地发送到服务器,并告诉它将您的正常出版物旁边的文档发布。
一个问题是集合中的文档顺序会发生变化,因为它们从一个订阅/发布中删除并放入另一个中。您可能需要使用排序 您的帮助程序中的Listings.find()可以防止订单更改。此外,根据延迟,当文档从一个出版物中删除并添加到另一个出版物时,列表可能仍会“闪烁”。
以下是代码的外观:
//Server side publish
Meteor.publish('listingsForSession', function(listingIds) {
check(listingIds, [String]);
if(listingIds.length > 0){
return Listings.find({_id: {$in: listingIds}});
}
});
//Client side subscription
Deps.autorun(function () {
if(Meteor.userId()){
Meteor.subscribe("listingsForSession", Session.get("listingIdsToKeep"));
}
});
//Click handler to keep track of documents that have been liked/disliked
Template.listings.events({
'click .like, click .dislike': function(event){
event.preventDefault();
var listingId = $(event.currentTarget).data("id"); //Or however you get the document _id
var listingIdsToKeep = Session.get("listingIdsToKeep");
listingIdsToKeep.push(listingId);
Session.set('listingIdsToKeep', listingIdsToKeep);
}
});
不确定这是否是最佳解决方案,但它可以正常工作。