你怎么能创造一个被动的&非反应性流星模板?

时间:2013-12-27 06:10:52

标签: javascript meteor

我正在努力解决一个奇怪的问题。只要文档使用某个属性进行更新,它就不再与发布查询匹配。 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   | |
| |                 | |
| |                 | |
| |                 | |
| |                 | |
| |                 | |
| |                 | |
| |                 | |
| |                 | |
| |-----------------| |
|                     |
-----------------------

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);
    }
});

不确定这是否是最佳解决方案,但它可以正常工作。

相关问题