web-dev-qa-db-ja.com

Meteor.jsでDOMが更新された後のコールバック

私はこのMeteorプロジェクトを持っています: https://github.com/jfahrenkrug/code_buddy

これは基本的に、大きなテキストエリアとプレエリアを備えたツールであり、接続されているすべてのクライアントに自動的にプッシュされるソースコードスニペットを入力できます。

コードが変更されたときに自動的にhighlightSyntax関数を実行したいのですが、実際には機能しません。

Query.observeを試してみましたが、うまくいきませんでした。構文のハイライトが一度点滅してから、再び消えました。

だから私の質問は:DOMが更新された後にコードを実行するにはどうすればよいですか?

35

それをするためのハッキーな方法は:

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操作を実行できます。テンプレートがレンダリングされている時点ではまだDOMにないため、Meteor.defer(settimeout(f、0)と同じことを行います)を使用する必要があります。

DOMに挿入しなくてもテンプレートをレンダリングできることに注意してください。たとえば、これを行うことは完全に合法です。

console.log(Template.mytemplate())

そのため、テンプレートがレンダリングされるとき、それがDOMに含まれるという100%の保証はありません。テンプレートのユーザー次第です。

33
Geoff

Meteor 0.4.0以降、Template.myTemplate.renderedは、

呼び出されますonce Template.myTemplateのインスタンスがDOMノードにレンダリングされ、ドキュメントに入れられるとき初めて

詳細情報 http://docs.meteor.com/#template_rendered

29
Pierre De Wilde

現在のバージョンの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.
    });
   }
});

DOMが更新された後はコールバックはありませんが、保留中のすべてのDOM更新を Tracker.flush() で強制できます。

flush()を呼び出すと、DOMが更新されたことがわかり、必要なDOMの手動変更を実行できます。

3
n1mmy

この質問はかなり古いですが、2年後の解決策は 操作変換ライブラリとMeteor を統合し、クライアントでAceまたはCodeMirrorを使用することです。これにより、構文の強調表示が自動的に行われます。これには、人々が同時に編集できるという追加の利点があります。

私はあなたのためにすでに仕事をしました:)

2
Andrew Mao

Blaze Components (私は作成者の1人です)には、DOMが挿入、移動、または削除されたときにメソッドを呼び出すAPIがあります。 ここを参照 DOMが変更されたときにリアクティブ変数を作成する方法。

このアプローチの欠点は、DOM要素の属性が変更されても変更されないことです(class changeなど)。 DOM要素自体が変更された場合のみ。これはほとんどの場合に機能しますが、2番目が必要な場合は、単に MutationObserver を使用することをお勧めします。この場合、外部の変更にも対応できます。

1
Mitar

私はかなりうまく機能しているように見える小さなハックを見つけました:

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

私はMeteorのエキスパートではないので、いくつかの欠点があるかもしれませんが、今のところ何も見つかりません—少し汚いことを除いて!

0
Nico Prat

_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_が問題の原因であると確信しています。

0
Todo