私は流星に非常に慣れていないので、ここで非常に基本的なものが欠けている場合は申し訳ありません.
流星をチェックするための非常にシンプルなテキストパッド スタイルのアプリを作成するのは楽しいだろうと思いました。todo アプリを使用して、データ構造を「リスト」と「todos」ではなく「フォルダー」と「ドキュメント」に変更したので、フォルダーのリストがあり、フォルダーをクリックするとドキュメントのリストが表示されますそのフォルダに。
次に、リスト内のドキュメントの 1 つがクリックされたときに、単一の「ドキュメント」の「コンテンツ」属性を表示するコードを追加しました。
ace を使用して、ドキュメントのコンテンツにきれいな印刷を追加しています ( https://github.com/ajaxorg/ace )。ドキュメントのプレーンテキスト バージョンを含む非表示のテキストエリアを操作するように ace を設定しました。エディター オブジェクトはこのテキストを取得し、きれいに印刷します。
ace の問題は、ドキュメントの内容が変更されるたびに ace エディターを含むテンプレートを置き換えたくないということです (再初期化に 0.5 秒かかるため、すべての文字が入力されるたびにひどい経験になります!) . 代わりに、テキストエリア テンプレートを更新してから、ace API を使用して、テキストエリアの内容に基づいて入力を更新するようエディターに指示します。
さて、これは問題へのアプローチとしてはおそらく間違った方法ですが、最終的に 2 つのテンプレートを使用することになりました。1 つ目は、基礎となるモデルに反応する doc.contents を含むテキストエリアを含みます。
<template name="doc_content">
<textarea name="editor">{{content}}</textarea>
</template>
2 番目のものには、ace がきれいに印刷されたテキストを表示するために使用する「editor」div が含まれています。
<template name="doc_init">
<div id="editor"></div>
</template>
最初のテンプレートは (すべてのクライアントで) ユーザーが入力するたびに更新され、2 番目のテンプレートは新しいドキュメントを読み込むたびにのみ再読み込みされるという考え方です。
Template.doc_content.content = function() {
var doc_id = Session.get('viewing_itemname');
if (!doc_id) {
return {};
}
var doc = Docs.findOne({_id:doc_id});
if (doc && doc.content) {
// #1 Later
var editor = Session.get('editor');
if (editor) {
editor.getSession().setValue(doc.content);
}
return doc.content;
} else {
return '';
}
};
エディターの div にテキストを入力すると、 が呼び出されDocs.update(doc_id, {$set: {content: text}});
、各クライアントのテキストエリアの値が更新されます。これまでのところすべて順調です。
editor.getSession().on('change', function(){
var text = editor.getSession().getValue();
Docs.update(doc_id, {$set: {content: text}});
});
私がやりたいことは、変更を行ったクライアント以外のすべてのクライアントに対して、そのドキュメントの変更をサブスクライブし、変更されたばかりのテキストで editor.getSession().setContent() を呼び出し、テキストを取得することですテキストエリアから、それを使用してエディターを埋めます。
テキストエリアを含むテンプレートから呼び出しを行うことで、これを実行しようとしました (ドキュメントが更新されるたびに変更されるため、上記の #1 を参照してください)。ただし、エディタで値を変更すると が再度呼び出されるため、クライアントは無限ループに陥りますDocs.update
。
明らかに、これはテンプレートをレンダリングするときに発生しないため、これを防ぐことができる魔法が meteor にあると想定していますが、その方法はわかりません。
何かご意見は?
ティア!