私はこのMeteorプロジェクトを持っています: https://github.com/jfahrenkrug/code_buddy
これは基本的に、大きなテキストエリアとプレエリアを備えたツールであり、接続されているすべてのクライアントに自動的にプッシュされるソースコードスニペットを入力できます。
コードが変更されたときに自動的にhighlightSyntax関数を実行したいのですが、実際には機能しません。
Query.observeを試してみましたが、うまくいきませんでした。構文のハイライトが一度点滅してから、再び消えました。
だから私の質問は:DOMが更新された後にコードを実行するにはどうすればよいですか?
それをするためのハッキーな方法は:
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%の保証はありません。テンプレートのユーザー次第です。
Meteor 0.4.0以降、Template.myTemplate.rendered
は、
呼び出されますonce Template.myTemplateのインスタンスがDOMノードにレンダリングされ、ドキュメントに入れられるとき初めて。
現在のバージョンの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の手動変更を実行できます。
この質問はかなり古いですが、2年後の解決策は 操作変換ライブラリとMeteor を統合し、クライアントでAceまたはCodeMirrorを使用することです。これにより、構文の強調表示が自動的に行われます。これには、人々が同時に編集できるという追加の利点があります。
私はあなたのためにすでに仕事をしました:)
Blaze Components (私は作成者の1人です)には、DOMが挿入、移動、または削除されたときにメソッドを呼び出すAPIがあります。 ここを参照 DOMが変更されたときにリアクティブ変数を作成する方法。
このアプローチの欠点は、DOM要素の属性が変更されても変更されないことです(class
changeなど)。 DOM要素自体が変更された場合のみ。これはほとんどの場合に機能しますが、2番目が必要な場合は、単に MutationObserver を使用することをお勧めします。この場合、外部の変更にも対応できます。
私はかなりうまく機能しているように見える小さなハックを見つけました:
Template.myTemplate.onRendered(function() {
this.autorun(function() {
Meteor.setTimeout(function() {
// DOM has been updated
}, 1);
});
});
私はMeteorのエキスパートではないので、いくつかの欠点があるかもしれませんが、今のところ何も見つかりません—少し汚いことを除いて!
_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
_が問題の原因であると確信しています。