Javascript 自从Meteor升级到0.8.0后,模板;“提供”;当会话变量相关性更改时,不会触发回调

Javascript 自从Meteor升级到0.8.0后,模板;“提供”;当会话变量相关性更改时,不会触发回调,javascript,meteor,spacebars,Javascript,Meteor,Spacebars,自从升级到0.8.0后,我遇到了一个问题。 渲染的模板不再被激发(第一次除外) 我遵循了以下建议: 这没有帮助,所以我最终制作了这段代码(通过修改新的2示例) 主要区别在于更新是由会话变量更改而不是DB更改触发的 这完美地说明了问题所在,因为在本例中渲染只触发了两次: client/each.js Template.list.items = function () { return (Session.get('items') || 'None') }; var renderCount =

自从升级到0.8.0后,我遇到了一个问题。 渲染的模板不再被激发(第一次除外)

我遵循了以下建议:

这没有帮助,所以我最终制作了这段代码(通过修改新的2示例)

主要区别在于更新是由会话变量更改而不是DB更改触发的

这完美地说明了问题所在,因为在本例中渲染只触发了两次:

client/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);
client/each.html

<body>
  {{> list}}
</body>

<template name="list">
   {{#with items}}
   {{> justName}}
   {{/with}}
</template>

<template name="justName">
  {{name}}
</template>

{{>列表}
{{#带项目}
{{>justName}
{{/与}}
{{name}}
当由Session.set触发内容更新时,如何正确触发Template.justName.rendered回调


谢谢,

我确实为您提供了一个即时解决方案,但它可能需要重新思考一下您的实际代码。顺便说一下,这和这里的问题是一样的:

但这个问题是在如此不同的背景下提出的,因此有必要回答两次

那么为什么它不触发呈现回调呢?因为它不会重新渲染

Blaze对“如何对更改的依赖项作出反应”的处理方式非常不同,“更好”一词可能会说:它将标识存储“一”、“二”或“三”(在您的示例中是模板本身)的DOM节点,并只替换已更改的部分,即文本内容“一”、“二”或“三”。DOM节点本身以及模板保持完整。这也意味着,在几乎所有的实际场景中,您可以使用这个DOM节点执行的所有操作都不必重新执行。也就是说,如果对其设置动画,使用jQuery更改其文本颜色,则颜色和动画将保持在屏幕上,因此不需要渲染回调来重新执行该操作

在您的情况下,只需在“rerender”上重新调整您要执行的操作,问题就很容易解决:

然后,您必须做的唯一一件事就是在您的数据发生更改时触发它,或者手动触发,如下所示:

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
});
或者,像这样的反应:

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()

在您的特定示例中,“logRender”函数没有任何反应性依赖项,但如果您添加一些并将其放入
Deps.autorun()
,则每当依赖项发生更改时,它将可靠地重新运行


总之,Meteor 0.7.x及以下版本促使我们犯了一个错误,将“呈现”回调函数视为通用自动运行函数,这就是为什么我们现在遇到了麻烦,不得不修复我们的应用程序。

如评论中所述,这确实是Meteor的一个设计更改

在Meteor 0.8之前,模板是生成HTML的函数。每当该函数的任何反应依赖项发生更改时,都会重新计算该函数,从而重新创建由该模板生成的所有DOM节点(除了任何子模板或独立节点)。无论何时重新绘制,都会触发
呈现的
回调

这种行为会对性能造成相当大的影响,因为它需要重新呈现大量潜在的HTML,包括标识符和助手(取决于未更改的数据)。此外,使用其他库(如jQuery)修改创建的DOM元素也很困难,因为Meteor基本上控制了整个过程,每次都必须小心地重新运行jQuery代码

Meteor 0.8修复了这一问题,它只渲染了实际更改的DOM片段,直到模板中标识符的粒度——它的粒度要细得多。因此,模板的
rendered
回调仅在模板到达页面时触发一次,之后不再调用。这解决了许多性能问题,并允许jQuery和其他DOM操作与Meteor无缝协作,但也意味着当某些内容发生更改时,您将无法获得自动回调信号。但是,您可以通过帮助器来实现这一点,这些帮助器使用反应变量来处理特定的变化

有关Spacebars(新车把的替代品)工作原理的更详细列表,请参阅


另请参阅有关呈现回调的新文档:

因此,我昨天做了大量挖掘工作,试图找出与您遇到的问题完全相同的问题。我仍在挖掘,但我确实遇到了Devshop关于集成其他客户端JS库的讨论。在书中,Ted Blackman描述了他制作的一个包,用于在会话变量更改时触发事件。听起来像是你需要的。这篇演讲是在0.8.0之前发表的,所以我不确定该方案将如何实施,但可能值得一试

Devshop谈话-

会议临时议程-


Event Horizon-

我也有同样的问题,这看起来可能是设计上的改变。还没有找到解决方案。他的答案是完整的,我学到了一些东西。但是,这并没有解决我的问题,因为在Session.set()触发html(重新)生成之后,模板并没有像它应该的那样创建DOM,可能是因为许多级联模板。我不得不重写很多,不再依赖模板反应式计算来创建我需要的DIV。简言之,在呈现/创建节点后,我没有找到与调用我的javascript部分的“呈现”行为相竞争的方法。很抱歉听到这个消息,这取决于你的应用程序的方式