2015-07-10 73 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。希望能幫助到你!