在Meteor.js中更新DOM后的回调

时间:2012-04-11 16:10:45

标签: meteor

我有这个Meteor项目:https://github.com/jfahrenkrug/code_buddy

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

我想在代码更改时自动运行highlightSyntax函数,但它确实没有用。

我已尝试过query.observe,但这并没有太好用:语法高亮显示一次,然后再次消失。

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

9 个答案:

答案 0 :(得分:33)

一种愚蠢的方法是:

<强> foo.html

<template name="mytemplate">
  <div id="my-magic-div">
    .. stuff goes here ..
    {{add_my_special_behavior}}
  </div>
</template>

<强> foo.js

Template.mytemplate.add_my_special_behavior = function () {
  Meteor.defer(function () {
    // find #my-magic-div in the DOM
    // do stuff to it
  });
  // return nothing
};

每当渲染(或重新渲染)模板时都会调用该函数,因此您可以将其用作钩子来执行您想要执行的任何特殊DOM操作。你需要使用Meteor.defer(它与settimeout(f,0)的作用相同),因为在渲染模板时,它还没有在DOM中。

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

console.log(Template.mytemplate())

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

答案 1 :(得分:29)

从Meteor 0.4.0开始,Template.myTemplate.rendered提供了回调

  将Template.myTemplate的实例渲染到DOM节点并首次放入文档时,

称为一次

http://docs.meteor.com/#template_rendered

的更多信息

答案 2 :(得分:9)

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

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.
    });
   }
});

答案 3 :(得分:3)

更新DOM后没有回调,但您可以使用Tracker.flush()强制所有待处理的DOM更新。

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

答案 4 :(得分:2)

这个问题相当陈旧,但两年后的解决方案是集成operational transformation library with Meteor并在客户端上使用Ace或CodeMirror,它会自动突出显示语法。这具有允许人们同时编辑的额外好处。

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

答案 5 :(得分:1)

Blaze Components(我是作者之一)中,您有一个API,可以在插入,移动或删除DOM时调用方法。您可以see here在DOM更改时如何制作反应变量。

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

答案 6 :(得分:0)

似乎Template.myTemplate.rendered无法正常工作或我无法获得......

我需要在渲染了所有帖子的模板后加载TinyMCE内联,所以我有:

- 模板

<div id="wrapper">     
         {{#each posts}}
             <div class="editable">{{post}}</div>
         {{/each}}        
  </div>

- 和一个函数

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"
});

}

但是,控制台仅记录<div id="wrapper">而不是<div class="editable"> div,其中包含我的帖子。因此,在呈现模板之前似乎发生了Template.myTemplate.rendered回调,对吗?

编辑:我将Template.myTemplate.rendered代码放在setTimeout()内,似乎一切正常,所以我确定Template.myTemplate.rendered会导致问题。

答案 7 :(得分:0)

我刚刚发现了一个似乎工作得很好的小黑客:

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

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

答案 8 :(得分:-2)

我认为您可能希望将回调传递给

Meteor.startup(callback)

请参阅http://docs.meteor.com/#meteor_startup