您已通过以下说明正确识别了您的问题:
显然发生的是 Template.featuredCarousel.rendered 中的函数在模板的#each-part 完成之前或数据到达之前被调用。
模板的rendered
回调仅在您的模板实例首次插入 DOM 时调用一次,因此如果您的数据尚未准备好(从服务器获取)但 #each 块不会生成任何 HTML 元素并且当您实例化轮播时它会显示为空。
您可以做的是确保您的数据在rendered
回调触发之前准备就绪。显然你试图设置这个解决方案没有运气,你确定你像这样添加了默认的加载钩子吗?
Router.onBeforeAction("loading");
更好的解决方案是在渲染回调中监听数据库更改,并在首次获取项目时相应地重新初始化轮播,然后动态添加和/或删除。
HTML
<template name="carousel">
<div class="owl-carousel">
{{#each featuredPosts}}
{{! item declaration}}
{{/each}}
</div>
</template>
JS
function featuredPosts(){
return Featured.find();
}
Template.carousel.helpers({
// feed the #each with our cursor
featuredPosts:featuredPosts
});
Template.carousel.rendered=function(){
var options={...};
// first initialization
this.$(".owl-carousel").owlCarousel(options);
this.autorun(_.bind(function(){
// this is how we "listen" for databases change : we setup a reactive computation
// and inside we reference a cursor (query) from the database and register
// dependencies on it by calling cursor.forEach, so whenever the documents found
// by the cursor are modified on the server, the computation is rerun with
// updated content, note that we use the SAME CURSOR that we fed our #each with
var posts=featuredPosts();
// forEach registers dependencies on the cursor content exactly like #each does
posts.forEach(function(post){...});
// finally we need to reinit the carousel so it take into account our newly added
// HTML elements as carousel items, but we can only do that AFTER the #each block
// has finished inserting in the DOM, this is why we have to use Deps.afterFlush
// the #each block itself setup another computation and Deps.afterFlush makes sure
// this computation is done before executing our callback
Tracker.afterFlush(_.bind(function(){
this.$(".owl-carousel").data("owlCarousel").reinit(options);
},this));
},this));
};
我对 owl-carousel 不熟悉,所以我不确定 reinit 是否会正常运行(我已经快速检查了文档,但似乎还可以)。
对于没有 reinit 方法的类似 JS 插件(例如引导轮播),您可以先检查插件是否已实例化,然后将其销毁并重新创建,如下所示:
var carousel=this.$(".carousel").data("bs.carousel");
if(carousel){
// bootstrap carousel has no destroy either so we simulate it by pausing it
// and resetting the data attribute to null (it's a bit messy)
this.$(".carousel").carousel("pause");
this.$(".carousel").data("bs.carousel",null);
}
// initialize normally because previous instance was killed
this.$(".carousel").carousel({...});