在Meteor中,有没有办法检测数据何时完全加载到浏览器?

时间:2015-07-06 22:16:13

标签: meteor iron-router

之前可能已经提出过这个问题,但我似乎无法找到一种简单的方法。

我有一个Meteor页面,显示用户按时间顺序发布的消息(底部的最新消息)。我想要页面:

#1)根据URL

中提供的参数订阅消息(使用发布/订阅)

#2)渲染页面

#3)显示页面上的消息

#4)滚动到底部。

在启动滚动到底部之前,没有明显的方法可以知道1,2和3何时完成。 Meteor确实具有观察/添加功能,可以在将新消息添加到订阅时执行事件,但只有当文档插入Mongo时才会发生,并且在将结果显示给初始订阅时不会触发。

我将显示上述步骤的代码:

#1:使用发布/订阅订阅消息:在/client/messages.js

Template.messages.created = function() {
  this.autorun( function() {
    this.subscription = Meteor.subscribe("messages", Router.current().params.category);
  }.bind(this));
};

#2在/client/messages.html

中渲染页面
<template name="messages">
  {{#each messages}}
    {{messageText}}<br><br>
  {{/each}}
</template>

#3:显示页面上的消息:/client/messages.js

Template.messages.helpers({
  messages: function() {
    var category = Router.current().params.category;
    return Messages.find({category: category}, { sort: { messageDate: 1 } });
  },
});

这一切都有效,但不会自动滚动到底部。

我无法在Meteor onRendered部分添加jquery scroll命令,因为它在数据写入DOM之前运行。我可以做一个Meteor.setTimeout等待1秒然后滚动到底部,但是如果花费的时间超过一秒来用DOM填充订阅的数据则不行。

这是使问题复杂化的另一件事。我在URL中提供了 category 变量。当客户端选择另一个类别时,使用Meteor / Blaze pathFor,

{{pathFor 'messages' channelid='new'}}

浏览器不会重新加载/重新呈现页面,它只是更新URL参数,该参数触发自动运行以更改已订阅的消息。它只是将新数据写入DOM。因此,我不能用jquery $(document).ready来检测页面是否准备就绪(因为页面总是准备就绪),而且我不能在我的末尾使用像{{scrollToBottom}}这样的花哨的把手。在messages.html中{{#each}}因为它没有重新运行。

那么,有没有一种简单的方法来检测Meteor / Blaze何时完全将新数据写入浏览器?

1 个答案:

答案 0 :(得分:0)

如果我理解正确,你真的只想知道你的所有数据何时从服务器发布到客户端(这样你就可以做一些事情,在这种情况下,滚动到底部)。

Meteor.subscribe()的所有调用都会返回订阅句柄。这有一个ready()方法,告诉您所有数据都已发送。这包括在模板级别完成的(如果适合您的用例,您可能需要考虑这些)。更多信息: http://docs.meteor.com/#/full/Blaze-TemplateInstance-subscribe

有几种方法可以使用它 - 您需要确定适合您的方法。由于ready()是被动的,您可以使用它。但是,您可能会发现在订阅中实现onReady回调更容易(请参阅上面的文档)。

我怀疑你需要在渲染的模板中实现自动运行。这是为了避免数据在渲染之前到达的相反情况(因此回调过早触发)。这样的事情可以解决问题(注意你已经在模板创建功能中将订阅句柄设置为this.subscription):

Template.messages.onRendered(function() {
  var self = this;
  this.autorun(function(computation) {
    if(self.subscription.ready()){
      $(document).scrollTop($(document).height());
      computation.stop()
    }
  });
});

这应确保仅在呈现之后调用该功能,并且订阅中的数据已完成。执行滚动后,自动运行也会停止,如果新文档导致ready()不再真实(然后再次准备好),则停止继续调用 - 这可能会让页面重新滚动到底部的人感到惊讶! / p>