Meteor:模板用数据渲染后调用函数
Posted
技术标签:
【中文标题】Meteor:模板用数据渲染后调用函数【英文标题】:Meteor: Call function after template is rendered with data 【发布时间】:2014-10-10 19:42:45 【问题描述】:我想在轮播中显示一些帖子。对于轮播,我使用 OwlCarousel 。
<div class="owl-carousel" id="featured-carousel">
#each featuredPosts
<div>
<h2>
postTitle
</h2>
</div>
/each
</div>
我这样称呼我的轮播:
Template.featuredCarousel.rendered = function()
$('#featured-carousel').owlCarousel(
loop:true,
autoplay:true,
autoplayTimeout:3000,
items:1,
smartSpeed:1080,
padding:80
);
this.rendered = true;
;
我得到的结果是,猫头鹰基本上认为我只有一个项目可以在轮播中显示,这是多个 div。显然发生的是 Template.featuredCarousel.rendered 中的函数在模板的#each-part 完成之前或数据到达之前被调用。
如何使实例化轮播的函数仅在模板完全呈现后才被调用,包括所有数据?
非常感谢您的帮助。
P.S.:我使用 Iron-router 进行路由,如下所示:
Router.map(function()
this.route('home',
path: '/',
waitOn: function()
return Meteor.subscribe('featured');
,
data: function()
return featuredPosts: Featured.find();
);
);
P.P.S.:我也尝试过使用加载模板,但这也无济于事。
【问题讨论】:
【参考方案1】:您已经正确地指出了您的问题:
显然发生的是 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(...);
【讨论】:
非常感谢您的回答,对我帮助很大。我没有完全按照你的建议设置我的钩子,但我不太了解你的方式。这是适用于所有路由的通用路由器设置,还是我应该将此作为选项添加到该特定路由的 Router.map 部分? "loading" 是 iron-router 包提供的一个特殊的默认钩子,你可以在这里查看它的定义:github.com/EventedMind/iron-router/blob/devel/lib/client/… 它默认没有激活,所以你需要将它添加到 onBeforeAction 钩子中被您的路由器用作全局路由器设置。您还可以使用排除语法在某些路由上停用它。我无法在当前的 Iron-router DOCS.md 上找到这些解释,这曾经更清楚。 与 !项目声明 你的意思是一些 div、h1 等? 是的,只需将构成轮播项目的所有标签放在这里即可。 正确知道我遇到了很大的问题,似乎帮助者无法正常工作【参考方案2】:我们最好在 #each 结束之后而不是 onRender 之后从模板中调用辅助处理程序。
一旦循环结束并加载相同的 DOM,处理程序就会调用该函数。
就像你的情况一样,每次将处理程序放置为initializeCarousel
。
#each featuredPosts ! item declaration /each initializeCarousel
现在在帮助器中将其定义为:
Template.carousel.helpers( // feed the #each with our cursor
initializeCarousel: function()
$('#featured-carousel').owlCarousel(
loop:true, autoplay:true, autoplayTimeout:3000, items:1, smartSpeed:1080, padding:80
);
);
这将使轮播在加载数据后加载。希望这会有所帮助。
【讨论】:
我在文档中读到不建议在帮助程序中进行这样的“设置”或“数据操作”。我认为是因为助手可能会连续多次被调用,这可能会导致不必要的副作用。以上是关于Meteor:模板用数据渲染后调用函数的主要内容,如果未能解决你的问题,请参考以下文章
ES6 angular-meteor ng-table getData 函数未调用