在Meteor.js中更新DOM后回调

在Meteor.js中更新DOM后回调,meteor,Meteor,我有一个流星计划: 它基本上是一个有一个大文本区域和一个预区域的工具,允许您输入自动推送到所有连接客户端的源代码片段 我想在代码更改时自动运行highlightSyntax函数,但它实际上不起作用 我试过query.observe,但效果不太好:语法高亮显示闪烁了一次,然后又消失了 所以我的问题是:更新DOM后如何运行代码?更新DOM后没有回调,但是您可以强制所有挂起的DOM更新 调用flush()后,您知道DOM已经更新,因此您可以执行所需的任何手动DOM更改。我想您可能需要将回调传递给 Me

我有一个流星计划:

它基本上是一个有一个大文本区域和一个预区域的工具,允许您输入自动推送到所有连接客户端的源代码片段

我想在代码更改时自动运行highlightSyntax函数,但它实际上不起作用

我试过query.observe,但效果不太好:语法高亮显示闪烁了一次,然后又消失了


所以我的问题是:更新DOM后如何运行代码?

更新DOM后没有回调,但是您可以强制所有挂起的DOM更新


调用
flush()
后,您知道DOM已经更新,因此您可以执行所需的任何手动DOM更改。

我想您可能需要将回调传递给

Meteor.startup(callback)

参见

一个简单的方法是:

foo.html

<template name="mytemplate">
  <div id="my-magic-div">
    .. stuff goes here ..
    {{add_my_special_behavior}}
  </div>
</template>
无论何时呈现(或重新呈现)模板,都会调用该函数,因此您可以将其用作钩子来执行您想要执行的任何特殊DOM操作。您需要使用Meteor.defer(它与settimeout(f,0)的作用相同),因为在呈现模板时,它还不在DOM中

请记住,您可以在不将模板插入DOM的情况下呈现模板!例如,这样做完全合法:

console.log(Template.mytemplate())

因此,当呈现模板时,不能100%保证它最终会出现在DOM中。这取决于模板的用户。

从Meteor 0.4.0开始,
template.myTemplate.rendered
提供了一个回调

当Template.myTemplate的实例呈现到DOM节点并第一次放入文档时,调用一次


更多信息请访问似乎
Template.myTemplate.rendered
无法正常工作或我无法获取它

在呈现包含所有帖子的模板后,我需要加载TinyMCE inline,因此我有:

-模板 }

但是,控制台只记录
,而不记录包含我的帖子的
div。所以,似乎
Template.myTemplate.rendered
回调在呈现模板之前发生,对吗


编辑:我将
Template.myTemplate.rendered
代码放入
setTimeout()
中,所有这些似乎都正常工作,因此我确信
Template.myTemplate.rendered
会导致问题

这个问题已经很老了,但两年后的解决方案是在客户端集成一个Ace或CodeMirror,它会自动突出显示语法。这样做的另一个好处是允许人们同时进行编辑


我已经为您完成了工作:)

至于当前版本的Meteor(1.0),我们现在可以使用Tracker的功能

Tracker.autorun(function(e){
   var data = Router.current().data();
   if(data.key !== undefined){
       //the data is there but dom may not be created yet
     Tracker.afterFlush(function(){
       //dom is now created.
    });
   }
});
在(我是作者之一)中,您有一个API,它在插入、移动或删除DOM时调用方法。您可以了解如何在DOM更改时生成反应变量


这种方法的缺点是,当DOM元素属性改变时(比如
class
change),它不会改变。仅当DOM元素本身发生更改时。这适用于大多数情况,但如果您需要第二种,我建议您只需使用。在这种情况下,您还可以对外部变化做出响应。

我刚刚发现了一个似乎运行良好的小技巧:

Template.myTemplate.onRendered(function() {
    this.autorun(function() {
        Meteor.setTimeout(function() {
            // DOM has been updated
        }, 1);
    });
});

我不是一个流星专家,所以它可能有一些缺点,但我现在还没有找到任何-除了它有点脏

谢谢,但这并不意味着知道DOM何时可以加载页面。我需要知道由于来自服务器的更改数据,DOM何时完成更新。拥有这种功能将非常棒。类似于
Template.myView.onFlush(function(){})
或特殊事件。例如,我正在寻找一种在每次刷新时设置元素scrolltop的方法。可能吗?Thanks@LarZuK作为Meteor开发人员之一(我想我们现在都是开发人员,但我指的是4:)的原始团队),我认为这是一个好主意,我经常想要这样的东西,但我不确定它应该如何工作。如果我在控制台中键入
console.log(Template.myView())
,您有什么建议吗?在这种情况下永远不要调用该函数?另一种情况:假设我使用
var frag=Meteor.ui.render(template.myView)
将模板呈现给DOM节点,但在实际将
frag
插入页面之前,请等待几秒钟。您认为新回调应该在模板呈现到DOM节点时触发,还是在将这些DOM节点放到屏幕上时触发?(前者很容易,后者很难……)我实际上是通过使用window.setTimeout解决了这个问题,因为Meteor.setTimeout在从query.observe调用时通过一个异常来解决的。我对此有一些计时问题。我必须使用很长的几秒钟超时时间,因为在渲染之前似乎仍然有延迟
Template.contextualFeed.feedItems=->Meteor.defer->console.log“Template.contextualFeed.feedItems delayed”console.log$(“abbr.timeago”)#->将日志记录为[],再加上查找它们的延迟$(“abbr.timeago”).timeago()Feed.find()
Hmm。。。可能是因为Feed.find()首先需要从Feed模型中获取数据?也许是往返旅行?当它获取数据时,还没有真正弄明白这一点……这个仍然有效,谢谢!现在只需要编写一些不同的代码:Template.templateName.helpers({add_my_special_behavior:function(){…});你可能想知道流星的起源行为。上面写着:这些日子真的不管用。请参阅更新DOM时不会调用此回调,例如,在模板中的
{{{each}}
中添加新元素时。只有在呈现Template.myTemplate的实例时,才会调用它
Template.myPosts.rendered = function(){
      console.dir($("div"));
      tinymce.init({
          selector: "div.editable",
          inline: true,
          plugins: [
              "advlist autolink lists link image charmap print preview anchor",
              "searchreplace visualblocks code fullscreen",
              "insertdatetime media table contextmenu paste"
          ],
          toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
});
Tracker.autorun(function(e){
   var data = Router.current().data();
   if(data.key !== undefined){
       //the data is there but dom may not be created yet
     Tracker.afterFlush(function(){
       //dom is now created.
    });
   }
});
Template.myTemplate.onRendered(function() {
    this.autorun(function() {
        Meteor.setTimeout(function() {
            // DOM has been updated
        }, 1);
    });
});