像Facebook一样在meteor中加载新帖子

像Facebook一样在meteor中加载新帖子,meteor,Meteor,我正在学习流星。我按照教程创建。如果有人提交一篇文章,meteor将为所有用户重新呈现模板。如果有数百篇帖子,那么用户将返回页面顶部,并且不知道他在哪里,这可能会非常烦人。我想实现一些类似于facebook的东西。提交新帖子时,模板不会呈现,而是会出现一个按钮或链接。单击它将导致模板重新渲染并显示新帖子 我在考虑使用集合上的observeChanges来检测任何更改,它确实会阻止页面显示新帖子,但显示新帖子的唯一方法是重新加载页面 Meteor.publish('posts', function

我正在学习流星。我按照教程创建。如果有人提交一篇文章,meteor将为所有用户重新呈现模板。如果有数百篇帖子,那么用户将返回页面顶部,并且不知道他在哪里,这可能会非常烦人。我想实现一些类似于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(); });
});
这条路对吗?如果是,我如何提醒用户新帖子?否则,有什么更好的方法来实现这一点


谢谢

这是一个棘手的问题,但也很有价值,因为它涉及到在许多情况下都适用的设计模式。其中一个关键方面是想知道有新数据,但不想向用户显示。我们还可以假设,当用户确实想要查看数据时,他们可能不想像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());
  }
});

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

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

这似乎不起作用。它会停止重新渲染,但newData从未设置为true。抱歉。看起来subscriptionsReady可能不是反应式的,文档不清楚,但补充模板帮助器是。因此,自动运行不会被触发。相反,您可能需要在subscribe函数中的subscription句柄或onReady回调上使用ready方法。