Meteor 渲染回调和应用 jQuery 插件
Posted
技术标签:
【中文标题】Meteor 渲染回调和应用 jQuery 插件【英文标题】:Meteor rendered callback and applying jQuery Plugins 【发布时间】:2014-10-18 15:57:53 【问题描述】:在将 jQuery 插件(如滑块或同位素)应用到从 Meteor 加载动态内容的 DOM 元素集合时寻找模式。
如果您调用template.rendered
(doc here) 似乎是一个合乎逻辑的选择。渲染模板时应用 jQuery。
根据Blaze wiki template.rendered
现在只调用一次。听起来不错。然而,它没有提到 template.rendered
在模板的内容被应用到 DOM 之前 被调用。
因此推荐的方法是将内部元素放入 #each 子模板中,然后在其rendered
回调中调用 jQuery。
但是:大多数 jQuery 插件不是这样工作的。它们需要在父 DOM 元素上调用,并且子 DOM 元素需要已经就位。
有些人甚至推荐a setTimeout on the parent element to approximate when the child elements will be rendered。这对我来说听起来不够可靠。
这是一个常见的例子:
page_slider.html
<template name="page_slider">
<div class="slider">
<ul class="slides">
#each slide
> slider_item
/each
</ul>
</div>
</template>
page_slider.js
Template.page_slider.rendered = function()
/*
* Can't initialise jQuery slider here as
* all inner DOM elements don't exist.
*
*/
;
查看子模板。
slider_item.html
<template name="slider_item">
<li class="slide"><img src="image"/></li>
</template>
slider_item.js
Template.slider_item.rendered = function()
/*
* Can't initialise jQuery slider here either
* as I don't know if all slide elements have been loaded
*
*/
;
从上面的示例可以看出,没有机会知道所有幻灯片何时已加载到 DOM 中,因此无法调用 jQuery 插件。
想知道我是否忽略了某些东西,或者目前是否有其他人正在使用的常见模式。
【问题讨论】:
看看这 2 个答案,我认为您正在解决的具体问题已得到详细解决。 ***.com/questions/25354070/… & ***.com/questions/25450826/… 【参考方案1】:您也可以使用此答案中指定的Meteor.defer()
:
https://***.com/a/31414707/3051080
Template.templateNotInDomYet.onRendered(function()
Meteor.defer(function()
$(//code);
);
);
【讨论】:
【参考方案2】:我用于解决此目的的模式如下:
首先,我将用于提供 #each
块的光标外部化到一个单独的辅助函数中,因为我们稍后将重用它。
// given a slider, return associated slides from the collection
function slides(slider)
return Slides.find(
sliderId:slider._id
);
// assumes the slider template is called with a slider as data context
Template.slider.helpers(
slides:function()
return slides(this);
);
<template name="pageSlider">
> slider mySlider
</template>
Template.pageSlider.helpers(
mySlider:function()
return Sliders.findOne(
name:"mySlider"
);
);
现在我们要做的是在 #each 块完成将我们的项目插入 DOM 之后执行代码,因此我们将“侦听”#each
块正在侦听的同一个响应式数据源to :这就是我们将游标声明为单独函数的原因。
我们将设置一个响应式计算来检测对底层 Slides
集合所做的更改,我们将执行一些代码,等待 #each
块在 DOM 中呈现项目,然后重新初始化 @ 987654327@滑块。
Template.slider.rendered=function()
this.autorun(_.bind(function()
// we assume that the data context (this.data) is the slider doc itself
// this line of code makes our computation depend on changes done to
// the Slides collection
var slidesCursor=slides(this.data);
// we wait until the #each block invalidation has finished inserting items
// in the DOM
Deps.afterFlush(function()
// here it is safe to initialize your jQuery plugin because DOM is ready
);
, this));
;
Deps.afterFlush
向我们保证,我们会在 #each
块所暗示的 DOM 渲染过程完成后运行我们的插件初始化代码。
setTimeout
hack 假设它会在刷新周期结束后触发,但它是丑陋的,因为 Deps
API 提供了一种专门设计用于在当前刷新周期结束后运行代码的方法。
快速回顾一下,这就是这段代码在后台发生的事情:
Template.slider.rendered
已被调用,但 #each
块尚未呈现您的滑块项。
我们的反应式计算已设置完毕,我们会监听来自 Slides
集合的更新(就像 #each
块在其自己的不同计算中所做的那样)。
一段时间后,Slides
集合被更新,#each 块计算以及我们的自定义计算都无效 - 因为它们依赖于 SAME 游标 - 因此将重新运行。现在棘手的部分是我们无法确定哪个计算将首先重新运行,它可能是一个或另一个,以一种不确定的方式。这就是为什么我们需要在 Deps.afterFlush
回调中运行插件初始化。
#each
块逻辑被执行,项目被插入到 DOM 中。
刷新周期(重新运行每个无效的计算)完成,我们的Deps.afterFlush
回调因此被执行。
此模式允许我们在新项目被添加到模型并随后由Blaze
在 DOM 中呈现时重新初始化我们的 jQuery 插件(轮播、类似砖石的东西等...)。
重新初始化过程取决于插件,大多数情况下,如果存在,您将不得不调用 reinit 方法或手动销毁并重新创建插件。
Meteor 手册对Deps
和Blaze
内部提供了很好的解释和示例,这绝对是推荐阅读:
http://manual.meteor.com/
【讨论】:
哇。非常感谢您花时间解释这一点。我还花了 30 分钟阅读手册中的 Deps。了解 Deps 的工作原理确实有助于我对 Meteor 的整体理解。 老兄,太棒了。我希望我能 +10。以上是关于Meteor 渲染回调和应用 jQuery 插件的主要内容,如果未能解决你的问题,请参考以下文章
由于 Meteor 升级到 0.8.0,当 Session 变量依赖发生变化时,不会触发模板“rendered”回调
如何将第三方 JavaScript 库添加到 Meteor 应用程序?