在将jQuery插件(如滑块或同位素)应用于从Meteor加载动态内容的DOM元素集合时,寻找一种模式。
如果你致电template.rendered
(doc here)似乎是一个合乎逻辑的选择。渲染模板时应用jQuery。
根据Blaze wiki template.rendered
现在只调用一次。听起来不错。但是,在模板的内容应用于DOM之前,没有提到template.rendered
被称为。
所以推荐的方法是将内部元素放入{{#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插件。
想知道我是否忽略了某些东西,或者目前是否存在其他人正在使用的常见模式。
答案 0 :(得分:12)
我用于解决此问题的模式如下:
首先,我将用于在单独的辅助函数中提供#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
块的相同反应数据源正在听:这就是为什么我们将光标声明为一个单独的函数。
我们将设置一个反应计算来检测对底层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
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
内部的精彩解释和示例,这绝对是推荐读物:
答案 1 :(得分:0)
您还可以使用此答案中指定的int main() {
// Declare your numbers.
int answer;
int number1, number2;
// Get input from the user.
printf("Enter a number\n");
scanf("%d",&number);
printf("Enter another number\n");
scanf("%d",&number2);
// Add them together:
answer = add(number1, number2);
// Tell the user.
printf("The result of those numbers are %d\n",answer);
}
:
https://stackoverflow.com/a/31414707/3051080
Meteor.defer()