web-dev-qa-db-ja.com

underscore.jsのネストされたテンプレート

どういうわけか、アンダースコアテンプレートからDOM要素を取得して、別のテンプレートとして使用することは可能ですか?

私のアプリは、アイテムと概要を含むループを含むドキュメントをレンダリングする必要があるという考えです。時折、要約またはいくつかのアイテムのみを再レンダリングする必要があるため、ドキュメント全体を再レンダリングすることはできません。

ただし、アプリユーザーがドキュメント用に独自のテンプレートを作成できるように簡単にしたいと思います。ドキュメントの1つのファイルにすべてを保存すると、より簡単になると思います。

私はこのようなものを使用しようとしています:

_<script type="text/template" id="document-template">
    <div id="document">
        <h1><%= name %></h1>
        <ul class="items">
            <% _.each(items, function(item) { %> 
                <li><%= item %></li>
            <% }); %>
        </ul>
        <div id="summary">
            <p>Total items: <%= totalitems %></p>
        </div>
    </div>
</script>
_

これで、このvar documentTemplate = _.template($('#document-template').html());を簡単に実行してこれをドキュメントテンプレートに変換できますが、サマリーパーツをテンプレートに、リストアイテムもテンプレートに変換したいと考えています。

私はこのようなことをすることができます:

_var summaryTemplate = _.template($('#document-template #summary').html());
var itemTemplate = _.template($('#document-template .items li').html());
_

PS。実際、私はjQueryの$ .getを使用して外部ファイルからテンプレートをロードしています。このようにして、1つの大きな文字列でドキュメントテンプレートを取得します。そこから、documentTemplate = _.template(loadedString);だけを実行できます。

これで、文字列から#summary要素を抽出できれば、動作するはずです。しかし、文字列をDOM要素(var domElement = $(loadedString))に変換しようとすると(つまり、summaryTemplate = _.template($('#summary',domElement).html());の場合)、アンダースコアが<% =%>タグはもうありません。

45
ragulka

ネストされたテンプレートをテンプレート割り当ての変数としてメインテンプレートに渡すことができます。例:

HTML:

<script type="text/template" id="sub_template">
  <article>
    <h1>id: <%= id %><h1>
  </article>
</script>

<script type="text/template" id="main_template">
  <% for (var i = 0; i < num; i++) { %>
    <%= renderSub({id:i}) %>
  <% } %>
</script>

JS:

 var renderSub = _.template( $('#sub_template').remove().text() ),
     renderMain = _.template( $('#main_template').remove().text() );

  renderMain({num:5, renderSub:renderSub});
67
Jon z

遊び場

/////// TEMPLATES //////

    var mainTemplate = "<ul> \
                          <% _.each(items, function(item) { %> \
                               <%= listItem({item:item}) %> \
                          <% }); %> \
                        <ul>";

    var subTemplate = '<li><%=item %></li>';


/////// MODEL (our data) //////

    var model = {
        items : [1,2,3,4,5]
    }


/////// COMPILE //////

    // add the subTemplate to the model data, to be passed to the mainTemplate
    model.listItem = _.template(subTemplate);

    // Render main template to the DOM
    document.body.innerHTML = _.template(mainTemplate, model);
5
vsync

一度にすべてを1つのテンプレートとしてロードし、後でその一部を再度ロードする代わりに、それらを複数のテンプレートとして分離します。

メインのドキュメントテンプレートと要約テンプレートを用意します。最初の読み込みでは、ドキュメントテンプレートを取得してから、サマリーテンプレートを取得し、最初のテンプレートからコンパイル済みDOMに挿入します。その後、いつでも2番目のテンプレートを再ロードできます。次の手順を参照してください。

1)以下に示す初期テンプレートをロードします。

<script type="text/template" id="document-template">
    <div id="document">
        <h1><%= name %></h1>
        <ul class="items">
            <% _.each(items, function(item) { %> 
                <li><%= item %></li>
            <% }); %>
        </ul>
    </div>
</script>

2)これがDOMにコンパイルされたら、次に示すように、アンダースコアを介して2番目のテンプレートをロードします。

<script type="text/template" id="summary-template">
    <div id="summary">
        <p>Total items: <%= totalitems %></p>
    </div>
</script>

3)$( "#document")。append(summaryTemplate)、またはコンパイルされたテンプレートを保持している変数を呼び出します。

4)サマリーをリロードする必要がある場合は、手順2と3を繰り返します。ただし、既存の$( "#summary")を削除してから再度追加することを除きます。

これと同じ戦略をアイテムに使用することもできます。既存のdivを正しい順序で上書きするように、正しいjQueryセレクター/メソッドを使用していることを確認してください。素子。

2
Axle

私は会話に3年遅れていることを知っていますが、これらの答えはどれも、私の最新のプロジェクトでの状況にまったく当てはまりませんでした。そして、私が最初にこれを行うことを考えていた方法が機能するようになったので、この質問のタイトルが示すように、他の誰かが実際にunderscore.jsテンプレートをネストしたい場合に備えて、投稿する必要があると考えました。

私の要件は基本的に:

1)テンプレートに動的な部分がある場合、テンプレート全体を更新されたデータで再レンダリングする必要なく、それらを個別に再レンダリングできるはずです。

2)動的な部分を親テンプレートと同じレベルの独自のテンプレートに分割する必要はありません。むしろ、一種のテンプレート階層が必要です。それ自体に必要なすべてのサブテンプレートを宣言するテンプレートです。

Underscore.jsのネストされたテンプレートの概念は、PHPなど)と同じです。次のコードは、「PHPのエコー」の例です。

<?php echo '<?php echo $var_unknown_until_runtime; ?>'; ?>

このネストされた構文は非常に複雑で混乱を招く可能性がありますが、考え方は簡単です。

後で値をエコーするエコーコード。

これはUnderscore.jsテンプレートにも適用されます。


コードは次のようになります。

<script type="text/template" id="outer-tpl">
    <%= value %>

    <script type="text/template" id="inner-tpl">
        <%= '<%= value %\>' %> <!-- NOTE how the inner '>' is escaped ('\>') -->
    <%= "</script\>" %> <!-- NOTE same thing -->
</script>

これを少し分解してみましょう。最初のNOTEのある行がここでの重要な行です。通常、Underscoreがこのテンプレートをコンパイルすると、valueの値が外部テンプレートと内部テンプレートの両方に出力されることが期待されます。これを防ぐためにいくつかのことを行いました。

1)ネストされたアンダースコアステートメントを文字列に変換します。

2)その文字列を補間します(<%= "string here" %>)。

3)最後のエスケープ>ネストされたアンダースコアステートメント(\>)。これにより、アンダースコアの正規表現がこれをステップ2の開始タグ(<%=)。この文字列がエコーされると、エスケープ文字が削除され、%>、次のパスでアンダースコアによって解釈される準備ができています。

この例の2番目のNOTEで同じことを行うと、ブラウザは最初のscriptタグを終了できなくなります。ネストされたscriptタグは技術的に許可されていないため、ブラウザは最初の文字シーケンスを探します:</script>その後、スクリプトの実行を終了します。これにより、ブラウザがこのシーケンスを認識できなくなります。

より詳細な例については、これを参照してください JSFiddle


免責事項

私は、これをこの種のことをするための最良の方法の近くのどこかとして支持しません。結局のところ、それは非常にハックです。 @John zの答えは私の選択肢ではなかった最初の要件を破りますが、テンプレート内の動的な部分を独自のテンプレートに分割する他のオプションの方が扱いやすいかもしれません。あまり整理されていません。

DOM内のこれらすべてのネストされたscriptタグの場所は、追跡が難しくなる可能性があります(ネストされたscriptタグは、外部テンプレートを挿入するときと場所に動的に挿入されるため) 。重複のリスクが高く、維持するのが面倒です。

テンプレートのネストの難しさは、ネストのレベルごとに大幅に増加します(ネストされたテンプレートにテンプレートをネストするには、すべてを再度エスケープする必要があるなど)。フィドルには、この例が含まれています。

1
bowheart