我想知道有没有办法知道#each循环是否“就绪”。 “就绪”是指它已渲染所有节点并插入到DOM中。我什至不谈论onRendered
回调(旧的rendered
)。我试过了
<template name="myTemplate">
<div class="some-class">
{{#if Template.subscriptionsReady}}
{{#each messages}}
<div>{{text}}</div>
{{/each}}
<script>
$(".some-class").trigger("LOOP_READY")
</script>
{{/if}}
</div>
</template>
Template.myTemplate.onRendered(function(){
this.$(".some-class").on("LOOP_READY", doSomething)
})
但这也不起作用。我不想使用计时器。
更新
messages
是当前对话框的文本消息的集合,dialogId
是存储在Session
中的反应变量。Template.myTemplate.onCreated(function(){
var self = this;
self.autorun(function(){
self.subscribe("messages", Session.get("dialogId"))
})
})
因此,如果有人更改dialogId,则myTemplate会加载另一条对话框消息,并且我想知道该消息何时准备就绪,才能滚动到特定消息。简单的
onReady
不起作用,因为在呈现所有消息并获得其自身高度之前,我无法准确地调用scrollTop。 最佳答案
当Spacebars {{#each}}
块已将其跨越的每个项目都渲染到DOM中时,没有简单的方法来获得通知。
最好的解决方案是使用另一个反应式计算(Tracker.autorun
)来观察消息游标的变化。
每次修改消息列表时,您都可以使用Tracker.afterFlush
在完成其他所有反应式计算以执行其工作之后运行任意代码。{{#each}}
块是这些计算之一,其作用是听取您作为参数提供给它的反应性数据源,并将其Template.contentBlock
重新渲染为从源中获取的项目重复进行的次数,当前项目为当前数据上下文。
通过侦听与{{#each}}
块帮助程序完全相同的反应式数据源,并在其完成自己的反应式计算后运行代码,您可以得到实际的请求行为,而无需依赖某些怪异的setTimeout
技巧。
这是此模式的完整实现:
的HTML
<template name="myTemplate">
<div class="some-class">
{{#if Template.subscriptionsReady}}
{{#each messages}}
<div class="message">{{text}}</div>
{{/each}}
{{/if}}
</div>
</template>
JS
// declare your reactive data source once to reuse the same in multiple places
function messagesCursor(){
return Messages.find();
}
Template.myTemplate.helpers({
messages: messagesCursor
});
Template.myTemplate.onRendered(function(){
this.autorun(function(){
// we need to register a dependency on the number of documents returned by the
// cursor to actually make this computation rerun everytime the count is altered
var messagesCount = messagesCursor().count();
//
Tracker.afterFlush(function(){
// assert that every messages have been rendered
console.log(this.$(".messages") == messagesCount);
}.bind(this));
}.bind(this));
});