【问题标题】:Why my helper doesn't re-run when the collection I call inside it is updated?为什么当我在其中调用的集合更新时我的助手不会重新运行?
【发布时间】:2015-11-10 05:49:20
【问题描述】:

我有一个带有视频播放器的模板。它使用助手从 mongo 文档中获取视频源。这是它的样子:

助手:

'currentItemUrl' : function() {
    //I only have one project. Is there a better/cleaner way to obtain it than the one below?
    var currentProject = Projects.find().fetch()[0]; 
    //the function below will create an instance of videojs or update the current one (set the new source)
    loadPlayer();
    //I return the source url if I have one
    return currentProject.setup.player.item_loaded.url?currentProject.setup.player.item_loaded.url:"";
}

HTML 看起来像这样:

<video id="video_player" class="video-js vjs-default-skin" controls preload="auto"
    width = "{{videoWidth}}" height="videoHeight"
    poster="{{currentItemPoster}}">
    <source id="mp4" src="{{currentItemUrl}}" type='video/mp4' />
    <source id="webm" src="" type='video/webm' />
    <source id="ogg" src="" type='video/ogg' />
</video>

问题

当我在另一个模板中更新我的Projects 集合时,如何确保我的助手重新运行?既然我使用了Collection.find(),它不应该是反应式的吗?

【问题讨论】:

  • 你不应该在你的模板助手代码中加入任何副作用。他们应该只读取值。相反,请考虑使用onRendered 回调并在那里调用loadPlayer()
  • 我在问题中没有提到一个棘手的部分。我希望我的播放器与视频源无关。为了正确设置它的大小(无论源大小/比率是多少),我以rendered 函数的形式加载我的源一次,然后我连接loadedmetadata 以便首先以正确的比率加载videojs,然后尺寸。我可能会将整个事情(在loadedmetadata 事件之前)包装到template.autorun() 函数中的rendered 中,并摆脱助手。感谢您的评论@apendua。
  • 是的,这很有道理。

标签: javascript mongodb meteor meteor-helper minimongo


【解决方案1】:

至于您的第一个问题(在代码的 cmets 中),如果您在任何时间点只有一个文档,那么findOne 有一个更简单的方法:

var currentProject = Projects.findOne();

您可以简单地使用 || operator 来代替沉重的三元默认值:

//Always place the default on the right, since '' is falsey
return (currentProject.setup.player.item_loaded.url || '');

而且因为您使用find(或findOne,除了返回一个文档之外基本上是一样的)它总是反应式的。如果文档发生更改,则 Tracker 计算将失效,您的助手 uses such a computation

在底层,每个助手都会启动一个新的 Tracker.autorun。当它的反应性依赖发生变化时,助手会重新运行。 Helpers 依赖于它们的数据上下文、传递的参数和在执行期间访问的其他响应式数据源。

但是,正如apendua 在评论中指出的那样,您的助手会触发副作用 (loadPlayer()) - 这通常被认为是一种不好的做法,因为助手与吸气剂非常相似:您只是希望它返回数据,而不是改变任何东西。您可能希望为该作业运行另一个 Tracker computation

【讨论】:

  • 太棒了!非常感谢,这是清晰而有意义的。当我在 rendered 函数中的 this.autorun() 中包装我的帮助内容时,它就像一个魅力。
  • 我假设三元在代码可读性方面“很重”,但只是为了检查:它的性能是否较低?除了可读性差之外,在 if/then/else 计算的情况下,是否还有其他原因应该忽略它以支持另一种方法? (即不完全是我在这种情况下使用的那个,我同意|| 更简单)。
  • @Billybobbonnet 嗯,知道哪个性能更好并没有多大用处。我的意思是,如果您总体上设法为每运行 1000 次节省 10 毫秒的计算,那么您为什么要关心呢?为什么你的用户会?这种微优化只能在服务器端进行,用于极其特定的目的……你最大的瓶颈通常是 Web 的网络,而不是 CPU。
  • 由于我还是 Javascript 的新手,我想知道在这种情况下是否有更好的做法。并不是说我特别关注性能(或微优化)。无论如何,我想我的答案是你的。谢谢:-)
猜你喜欢
  • 2020-10-09
  • 2011-03-09
  • 1970-01-01
  • 2012-05-26
  • 2013-12-27
  • 2015-09-03
  • 2021-12-23
  • 1970-01-01
相关资源
最近更新 更多