Meteor呈现回调并应用jQuery插件
Meteor rendered callback and applying jQuery Plugins
将jQuery插件(如滑块或同位素)应用于加载了Meteor动态内容的DOM元素集合时,请查找模式。
如果您调用template.rendered
(此处为doc)似乎是一个合乎逻辑的选择。当模板被呈现时,应用jQuery。
根据Blaze维基的说法,template.rendered
现在只被调用过一次。听起来不错。然而,它没有提到template.rendered
在模板的内容应用于DOM之前被调用。
因此,推荐的方法是将内部元素放入{{#each}}子模板中,然后在其rendered
回调中调用jQuery。
但是:大多数jQuery插件都不是这样工作的。它们需要在父DOM元素上调用,并且子DOM元素需要已经就位。
有些人甚至建议在父元素上设置setTimeout,以估计子元素将在何时呈现。这听起来对我来说不够可靠。
这里有一个常见的例子:
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插件。
想知道是否有我忽略的东西,或者目前是否有其他人正在使用的常见模式。
我用于解决此问题的模式如下:
首先,我将用于馈送#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"
});
}
});
现在,我们想做的是在#每个块在DOM中插入完我们的项之后执行代码,所以我们将"监听"#each
块正在监听的同一个反应数据源:这就是为什么我们将光标声明为一个单独的函数。
我们将设置一个反应式计算来检测对底层Slides
集合所做的更改,并执行一些代码,这些代码将等待#each
块在DOM中呈现项目,然后重新初始化jQuery
滑块。
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
破解的工作原理是假设它将在刷新周期结束后触发,但由于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/
您也可以使用以下答案中指定的Meteor.defer()
:
https://stackoverflow.com/a/31414707/3051080
Template.templateNotInDomYet.onRendered(function(){
Meteor.defer(function(){
$(//code);
});
});
- 应用jQuery动画时出现意外的抖动效果
- 在应用 jQuery.Selected 时,使用 jQuery.Validate 来验证选择字段时,暴露错误
- 如何在应用jquery buttonset()后取消选中所有具有相同类名的单选框
- 动态加载内容后应用jQuery样式
- 在同一页面上的多个搜索框上动态应用 Jquery 中的搜索过滤器
- 在 scrollTop 上应用 Jquery 效果时遇到问题
- 对嵌套表单中的新字段重新应用 jquery - Rails 3
- 如何在 Backbone / Underscore 上应用 jQuery timeago 或 easydate
- 使用挖空.js隐藏/取消隐藏时不应用 jquery UI 主题
- 无法对同级 tr(表行)应用 jquery 切片方法
- CSS - 未应用 jquery 移动样式
- 仅在新内容中应用 jQuery
- 在应用 jquery 函数时 Id 是必需的吗?
- 在流星模板中重新应用 JQuery
- 了解JavaScript事件并应用jQuery事件/插件
- 如何在验证后应用jQuery淡入淡出效果
- 在JavaScript之前学习/应用jQuery
- 应用jquery插件:loudev.commultiselect
- 在动态驱动的表单上应用jQuery自动完成json数据源
- 在动态生成的html数据表上应用jQuery Resizable