2015-07-10 45 views
0

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

我正在考虑在集合上使用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(); }); 
}); 

这是正确的道路吗?如果是的话,我如何提醒用户新帖子?否则,执行此操作的更好方法是什么?

谢谢

回答

0

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

我认为这是覆盖您提出的所有要点的最简单模式。如果你没有时间戳,你有多个订阅(然后需要使用订阅处理)等,它会变得更加复杂。希望这有助于!

+0

这似乎并不奏效。它会停止重新渲染,但newData永远不会设置为true。 –

+0

对不起。它看起来像'subscriptionsReady()'可能没有反应(文件不清楚),但补充模板助手是。因此,自动运行不会被触发。相反,您可能需要在订阅处理中使用'ready()'方法或在subscribe函数中使用'onReady()'回调。 –

0

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