自从我升级到0.8.0后,我遇到了问题。 渲染的模板不再被触发(第一次除外)。
我遵循以下建议: https://github.com/avital/meteor-ui-new-rendered-callback/blob/master/new2/client/each.js
这没有帮助,所以我最终制作了这一小段代码(通过修改new2示例)。
主要区别在于更新是由Session变量而不是DB更改触发的。
这完美地显示了问题,因为渲染仅使用此示例触发两次:
的客户机/ each.js
Template.list.items = function () {
return (Session.get('items') || 'None')
};
var renderCount = 1;
var logRender = function () {
console.log("rendered #" + renderCount);
renderCount++;
};
Template.list.rendered = function () {
logRender();
};
Template.justName.rendered = function () {
logRender();
};
setInterval(function () {
Session.set('items', {name: Random.choice(["one", "two", "three"])});
}, 1000);
的客户机/ each.html
<body>
{{> list}}
</body>
<template name="list">
{{#with items}}
{{> justName}}
{{/with}}
</template>
<template name="justName">
{{name}}
</template>
如何在Session.set触发内容更新时正确触发Template.justName.rendered回调?
谢谢,
答案 0 :(得分:3)
我确实为您提供了即时解决方案,但它可能需要对您的实际代码进行一些重新思考。顺便提一下,问题就在这里:
Meteor 0.8.0 - Failed to operate DOM in rendered callback
但问题是在这样一个不同的背景下提出的,回答两次是有意义的。
那么为什么它不会触发渲染的回调呢?因为它不会重新渲染。
Blaze对待整个事情&#34;如何对变化的依赖关系作出反应&#34;非常不同,&#34;更好&#34;有人可能会说:它会识别你的&#34; one&#34;,&#34; two&#34;或&#34;三&#34; (在你的情况下,它是模板本身)存储在并且只是替换已经改变的部分,即文本内容&#34; one&#34;,&#34; two&#34;或&#34;三&#34;。 DOM节点本身以及模板完全保持不变。这也意味着,几乎在每个实际场景中,您在本DOM节点上所做的一切都不必重新完成。即如果你为它设置动画,使用jQuery更改它的文本颜色,颜色和动画将保留在屏幕上,所以你不需要渲染的回调来重新执行它。
在您的情况下,只需重新安排您想要做的事情即可轻松解决问题&#34; rerender&#34;:
var whatever = function(){
// whatever you want to do on data-change, in your case calling "logRender" (which needs to be renamed with Blaze, anyway..)
logRender();
}
然后你唯一需要做的就是在数据发生变化时手动启动它,如下所示:
setInterval(function () {
Session.set('items', {name: Random.choice(["one", "two", "three"])});
// calling the function when changing the data, knowing that it WON'T destroy the DOM node it affects
whatever();
}, 1000);
或反应性,像这样:
Deps.autorun(function(){
Session.get("items"); // our dependency, just has to be there, but you can also use it
whatever(); // will be fired whenever dependency changes
});
核心思想是消除重新执行在渲染回调中所做的事情的需要,因为DOM及其对象的身份(以及所有漂亮的jQuery效果)仍然完好无损。因此,重新做的只是依赖于特定的被动数据变化,这就是Deps.autorun()
的原因。
在您的特定示例中,您的&#34; logRender&#34;函数没有任何反应依赖,但如果你添加一些并将它放入Deps.autorun()
,它将在依赖项发生变化时可靠地重新运行。
作为一个结论,Meteor 0.7.x及以下版本驱使我们犯了错误,即处理&#34;渲染&#34;回调函数作为通用自动运行功能,这就是为什么我们现在遇到麻烦并且必须修复我们的应用程序。
答案 1 :(得分:0)
正如评论中所指出的,这确实是Meteor的设计变更。
在Meteor 0.8之前,模板是一个生成HTML的函数。只要其任何反应依赖关系发生变化,就会重新计算此函数,从而重新创建模板生成的所有DOM节点(除了任何子模板或隔离节点)。每当重新绘制时,都会触发rendered
回调。
这种行为会产生很大的性能影响,因为它需要重新呈现潜在的大量HTML,包括标识符和帮助程序,具体取决于尚未更改的数据。另外,它很难使用像jQuery这样的其他库来修改创建的DOM元素,因为Meteor基本上可以控制整个过程,每次都必须仔细重新运行jQuery代码。
Meteor 0.8通过仅渲染实际已更改的DOM片段来修复此问题,降低到模板中标识符的粒度 - 它更精细。因此,模板的rendered
回调仅在您的模板点击页面时触发一次,之后再也不会再次调用。这解决了许多性能问题,并允许jQuery和其他DOM操作与Meteor无缝协作,但也意味着当某些内容发生变化时,您将无法获得自动回调信号。但是,您可以通过帮助程序实现此目的,这些帮助程序将使用反应变量来处理更改的特定事物。
有关如何使用新的把手替代品Spacebars的详细列表,请参阅https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md
另请参阅有关渲染回调的新文档:http://docs.meteor.com/#template_rendered
答案 2 :(得分:0)
所以,我昨天做了很多挖掘工作,试图找出你所遇到的完全相同的问题。我还在挖掘,但我确实遇到过关于集成其他客户端JS库的Devshop演讲。在其中,Ted Blackman描述了他在Session变量发生变化时触发事件的包。这听起来像你需要的。这次谈话是在0.8.0之前给出的,所以我不确定这个包是如何实现的,但它可能值得一试。
Devshop Talk - https://www.youtube.com/watch?v=NdBPY98o6eM