【问题标题】:Facebook like load new posts in meteorFacebook喜欢在流星中加载新帖子
【发布时间】:2015-07-10 04:18:07
【问题描述】:

我正在学习流星。我按照教程创建了microscope。如果有人提交后流星将重新呈现所有用户的模板。如果有数百个帖子,这可能会非常烦人,然后用户将返回页面顶部并松散跟踪他的位置。我想实现类似于 facebook 的东西。当提交新帖子时,不会呈现模板,而是会出现一个按钮或链接。单击它将导致模板重新呈现并显示新帖子。

我正在考虑在集合上使用observeChanges 来检测任何更改,它确实会阻止页面显示新帖子,但显示它们的唯一方法是重新加载页面。

Meteor.publish('posts', function(options) {
  var self = this, postHandle = null;

  var initializing = true;

  postHandle = Posts.find({}, options).observeChanges({
    added: function(id, post) {

      if (initializing){
          self.added('posts', id, post);
      } 
    },
    changed: function(id, fields) {
      self.changed('posts', id, fields);
    }
  });

  self.ready();
  initializing = false;
  self.onStop(function() { postHandle.stop(); });
});

这是正确的道路吗?如果是,我如何提醒用户有新帖子?否则,有什么更好的方法来实现这一点?

谢谢

【问题讨论】:

    标签: meteor


    【解决方案1】:

    这是一个棘手的问题,但也很有价值,因为它涉及适用于许多情况的设计模式。关键方面之一是想知道有新数据但不想(还)向用户显示。我们还可以假设当用户确实想查看数据时,他们可能不想等待数据加载到客户端(就像 Facebook 一样)。这意味着客户端仍然需要在数据到达时对其进行缓存,而不是立即显示。

    因此,您可能想要限制发布中显示的数据 - 因为这不会将数据发送到客户端。相反,您希望将所有(相关)数据发送到客户端并将其缓存在那里,直到它准备好。

    最简单的方法是在数据中使用时间戳。然后,您可以将其与反应变量结合使用,仅在反应变量更改时将新文档添加到显示的集合中。像这样(代码可能在不同的文件中):

    // Within the template where you want to show your data
    Template.myTemplate.onCreated(function() {
      var self = this;
      var options = null; // Define non-time options
    
      // Subscribe to the data so everything is loaded into the client
      // Include relevant options to limit data but exclude timestamps
      self.subscribe("posts", options);
    
      // Create and initialise a reactive variable with the current date
      self.loadedTime = new ReactiveVar(new Date());
    
      // Create a reactive variable to see when new data is available
      // Create an autorun for whenever the subscription changes ready() state
      // Ignore the first run as ready() should be false
      // Subsequent false values indicate new data is arriving
      self.newData = new ReactiveVar(false);
      self.autorun(function(computation) {
        if(!computation.firstRun) {
          if(!self.subscriptionsReady()) {
            self.newData.set(true);
          }
        }
      });
    });
    
    // Fetch the relevant data from that subscribed (cached) within the client
    // Assume this will be within the template helper
    // Use the value (get()) of the Reactive Variable
    Template.myTemplate.helpers({
      displayedPosts = function() {
        return Posts.find({timestamp: {$lt: Template.instance().loadedTime.get()}});
      },
    
      // Second helper to determine whether or not new data is available
      // Can be used in the template to notify the user
      newData = function() {
        return Template.instance().newData.get();
    });
    
    // Update the Reactive Variable to the current time
    // Assume this takes place within the template helper
    // Assume you have button (or similar) with a "reload" class
    Template.myTemplate.events({
      'click .reLoad' = function(event, template) {
        template.loadedTime.set(new Date());
      }
    });
    

    我认为这是涵盖您提出的所有要点的最简单模式。如果您没有时间戳、有多个订阅(然后需要使用订阅句柄)等,情况会变得更加复杂。希望这会有所帮助!

    【讨论】:

    • 这似乎不起作用。它会停止重新渲染,但 newData 永远不会设置为 true。
    • 对不起。看起来subscriptionsReady() 可能不是反应式的(文档不清楚),但补充模板助手是。因此,不会触发自动运行。相反,您可能需要在订阅句柄上使用ready() 方法或在订阅函数中使用onReady() 回调。
    【解决方案2】:

    正如邓肯在他的回答中所说,ReactiveVar 是要走的路。我实际上已经用流星实现了一个简单的 facebook 提要页面,我在其中显示来自某个页面的公共帖子。我使用无限滚动将帖子添加到页面底部并将它们存储在 ReactiveVar 中。查看 github here 和现场演示 here 上的源代码。希望对您有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-14
      • 2017-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多