35

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

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

我想在代码更改时自动运行 highlightSyntax 函数,但它并没有真正起作用。

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

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

4

9 回答 9

33

一个hacky方法是:

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 中。这取决于模板的用户。

于 2012-04-12T08:27:07.727 回答
29

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

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

更多信息请访问http://docs.meteor.com/#template_rendered

于 2012-09-05T14:40:55.730 回答
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.
    });
   }
});
于 2014-12-09T08:44:57.630 回答
3

更新 DOM 后没有回调,但是您可以使用Tracker.flush().

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

于 2012-04-11T18:40:03.283 回答
2

这个问题很老了,但两年后的解决方案是集成一个操作转换库与 Meteor并在客户端使用 Ace 或 CodeMirror,它会自动突出显示语法。这具有允许人们同时编辑的额外好处。

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

于 2014-06-23T16:01:05.423 回答
1

Blaze Components(我是作者之一)中,您有一个 API,它在插入、移动或删除 DOM 时调用方法。您可以在此处查看如何在 DOM 更改时创建反应变量。

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

于 2015-10-15T01:30:52.467 回答
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 而不是div。<div class="editable">所以,似乎Template.myTemplate.rendered回调发生在模板渲染之前,对吧?

编辑:我将Template.myTemplate.rendered代码放在 asetTimeout()中,一切似乎都可以正常工作,所以我肯定Template.myTemplate.rendered会导致问题。

于 2014-06-22T08:54:02.683 回答
0

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

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

我不是 Meteor 专家,所以它可能有一些缺点,但我现在还没有找到任何东西——除了它有点脏!

于 2016-01-19T16:03:10.280 回答
-2

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

Meteor.startup(callback)

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

于 2012-04-12T04:13:13.120 回答