Javascript 如何创建反应式&;非反应性流星模板?

Javascript 如何创建反应式&;非反应性流星模板?,javascript,meteor,Javascript,Meteor,我正与一个奇怪的问题作斗争。一旦文档使用某个属性更新,它就不再与发布查询匹配。Meteor将其从DOM中删除,并将其从客户端集合中删除 我需要列表保持在原位,这样用户仍然可以返回并撤消他们的选择。然而,我需要他们不显示在下一页加载 如果我将整个集合发送到客户端,然后如果它返回的结果超过0,则将reactive false设置为false,那么我可以模拟我所追求的。刷新时,仅显示未选择的列表。显然,这对性能不好 我的发布查询基本上只是过滤出正确的列表类型,并提取 在用户没有选择喜欢/不喜欢的列表中

我正与一个奇怪的问题作斗争。一旦文档使用某个属性更新,它就不再与发布查询匹配。Meteor将其从DOM中删除,并将其从客户端集合中删除

我需要列表保持在原位,这样用户仍然可以返回并撤消他们的选择。然而,我需要他们不显示在下一页加载

如果我将整个集合发送到客户端,然后如果它返回的结果超过0,则将reactive false设置为false,那么我可以模拟我所追求的。刷新时,仅显示未选择的列表。显然,这对性能不好

我的发布查询基本上只是过滤出正确的列表类型,并提取 在用户没有选择喜欢/不喜欢的列表中。这是在增加限制,但我做不到 它不会丢失以前选择的列表

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   | |
| |                 | |
| |                 | |
| |                 | |
| |                 | |
| |                 | |
| |                 | |
| |                 | |
| |                 | |
| |-----------------| |
|                     |
-----------------------

这是一个有趣的问题。您并不是真正想让模板成为被动和非被动的,而是想办法在用户“会话”期间保持某些文档的发布,即使某个字段已更改,这通常会导致文档取消发布

想到的一个解决方案是,如果在当前会话期间添加了“喜欢”或“不喜欢”,则第二次发布可以保留那些被喜欢或不喜欢的文档。两个发布可以从同一个集合发布,结果是客户端上的集合是这两个发布的联合

因此,当用户单击“喜欢”或“不喜欢”时,您会将该文档的_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);
    }
});

不确定这是否是最好的解决方案,但它可以工作。

太棒了!这看起来很有希望。我醒来后会试试这个。另一件我尝试过但失败的事情是在会话中创建一个单独的数组。基本上,我会观察/自动运行查询,然后将旧/新数据合并到会话变量中。然后将该会话变量输入模板。然而,我有可怕的问题保持更新。这是伟大的!保持秩序和防止闪烁的关键是在做出喜欢/不喜欢之前将id插入会话数组。事实上,在listings控制器(而不是ui事件)中,我必须在Meteor-like方法周围包装一个带有0的setTimeout,以使其等待。太棒了,谢谢@Dysko!这与问题无关,但我注意到在您提供的代码中,您的助手正在使用find().fetch()并返回结果数组。我假设您正在模板中使用{{{each listings}}块来呈现每个项目。如果您可以绕过推送空的“no items card”的需要,那么最好返回从查找中得到的集合游标,而不是获取数组并返回数组。当你给{{{#each}}块一个集合游标时,Meteor会更聪明地只重新呈现改变的项目,而不是数组中的每个项目。谢谢你的提示!现在我想起来了,我应该能够在模板中通过在
每个
块之后添加一个节点来实现这一点。这样,滑动插件的末端仍然有一个额外的,Meteor不会删除它。