我在弄清楚Meteor.rendered的工作原理时遇到了一些问题。我正在尝试为Meteor中的实时变化设置动画,就像this question一样。每当我单击某个元素时,我都希望它闪烁。

但是,每次单击一个元素时,模板都会渲染两次,从而又两次触发动画。这是代码:

模板

<body>
  {{> myItemList}}
</body>

<template name="myItem">
  <div class="item {{selected}}">
    <h4>{{name}}</h4>
    <p>{{description}}</p>
  </div>
</template>

<template name="myItemList">
  {{#each items}}
    {{> myItem}}
  {{/each}}
</template>


Java脚本

Template.myItemList.helpers({
  items: function () {
    return Items.find();
  }
});

Template.myItem.helpers({
  selected: function () {
    return Session.equals('selected', this._id) ? "selected" : "";
  }
});

Template.myItem.events({
  'click .item' : function () {
    Session.set('selected', this._id);
  }
});

Template.myItem.rendered = function () {
  $(".item.selected").fadeOut().fadeIn();
};


我的理解是,每次调用Session.set时,都会重新运行将Session.get用作相同密钥的每个模板,如文档中所述。所以我的猜测是,也许Session.equals导致模板的2次重新运行?如果我使用以下代码更改selected帮助器:

Template.myItem.helpers({
  selected: function () {
    if (Session.get("selected")) === this._id)
      return "selected";
    else
      return "";
  }
});


然后动画将触发3次而不是2次。

考虑到所有这些,我的问题是:


为什么Template.myItem.rendered被触发两次?幕后到底发生了什么?
如何解决此问题,使动画仅触发一次?


答案详情

因此,对@Xyand解决方案发表评论:


使用click将动画移至Meteor.setTimeout()事件肯定可以,但是对我来说有点不客气。
该解决方案实际上非常简单,并且已在this question中给出。代码如下:

Template.myItem.rendered = function () {
  if (Session.equals('selected', this.data._id))
    $(this.firstNode).fadeOut().fadeIn();
};



我首先在一个具有不同模板标记的不同项目上尝试了该项目,但该项目不起作用,这就是为什么我创建此最小项目以查看问题出在哪里的原因。事实证明,要使其正常工作,您绝对需要在myItem模板内部调用一个子模板myItemList。如果模板看起来像这样,

<template name="myItemList">
  {{#each items}}
    <div class="item {{selected}}">
      <h4>{{name}}</h4>
      <p>{{description}}</p>
    </div>
  {{/each}}
</template>


因此,为rendered模板调用了每个辅助函数和myItemList函数,该代码将无法工作,因为在rendered函数内部,模板实例将具有未定义的.data属性。

最佳答案

该模板被渲染两次,因为同一模板的两个不同实例被渲染。一个将selected更改为"selected",另一个将其更改为""。这也解释了为什么在将equals切换为get时为什么有3个渲染。

将命令性javascript与声明性混合总是一团糟。所以这是我的两个建议:


if函数内添加rendered以确保仅在所选项目模板实例中调用转换。
将过渡移到事件本身。您可能需要使用Meteor.setTimeout


将过渡放在rendered中可能不是最佳选择,因为每次模板渲染时都会发生。例如,如果name更改。想一想当代码变长时会发生什么...

关于javascript - 尝试在Meteor.js中对实时更改进行动画处理时,为什么会触发Template.mytemplate.rendered两次?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18409249/

10-11 13:03