之前可能已经提出过这个问题,但我似乎无法找到一种简单的方法。
我有一个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何时完全将新数据写入浏览器?
答案 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>