2

私の Web アプリケーションは現在 Tapestry 5.2.6 を使用しています。次の要件を持つ新しい機能を書きたいと思います。

  • ユーザーはギャラリー内のアイテムをクリックして、詳細ビューを示すライトボックスを表示できます。これには、説明、コメント、適切な資格情報がある場合の販売者コントロール、およびページを離れずに購入する機能が含まれます。
  • ギャラリー ビューまたは詳細ビューのどちらにあるかを反映するように、URL を更新する必要があります。
  • HTML5 pushState をサポートするブラウザーでは、URL の変更は動的である必要があります。古いブラウザーでは、ページ全体の更新が許容されます。
  • ギャラリー ページと詳細ページの両方がクロール可能である必要があります。Javascript を使用しないユーザーには、完全にマークアップされたページが表示されます。
  • 速度 - タペストリーに期待できるよりもはるかに高速である必要があります。

私の計画は、サーバーでもクライアントでも同じように評価できるテンプレート言語を選択して実装することです。最初のページ読み込みでは、サーバー上でテンプレートをレンダリングできます。その後の更新では、アイテムのビューモデル オブジェクトを JSON としてクライアントに渡し、そこでテンプレートを評価できます。

ここまでは順調ですね。問題は、私が調べたテンプレート言語のどれもが、将来に向けて進んでいくことに満足できるほど強力ではないということです。ケーススタディとして、次のいずれかを検討してください。

  • 口ひげ
  • ほこり
  • ホーガン
  • ハンドルバー

次のような「ラッピング」変換を行う力があるようには見えません。

# base template
{>widget}
    <span class="content">Hello world</span>
{/widget}

# widget template
<div class="widget">
    {>widget_body/}
</div>

# rendered output
<div class="widget">
    <span class="content">Hello world</span>
</div>

ラップされたコンテンツはベース テンプレートから取得され、ウィジェット テンプレートの出力が両側でそれを囲んでいることに注意してください。上記の言語でこれを達成するために私が知っている唯一の方法は、次のようなテンプレートです。

{>open_widget/}
    {>widget_body/}
{>close_widget/}

つまり、すべてのコンポーネントに 2 つのテンプレート (オープナーとクローザー) があり、どちらにも閉じられていないタグが含まれています。(公平を期すために、Dust はブロックとインライン パーシャルを使用してこれをある程度エレガントに行うことができますが、インライン パーシャルはテンプレートに対してグローバルであるため、テンプレートごとにウィジェットの使用は 1 回に制限されます。)

テンプレートに関する私の質問は次のとおりです。

  • LinkedIn や Twitter などの業界のリーダーがこれらのテクノロジを使用して素晴らしい成果を上げていることを私は知っています。求めすぎですか?それらのいずれかを使用したことがある場合、「ラッピングの問題」にどのように対処しましたか?
  • 私が調査したいくつかのソリューションは、それをサポートしているようです。アンダースコアと ejs は、埋め込みコードを使用した長期的なソリューションとして私を不安にさせます。およびクロージャ テンプレート。現在、私には Closure が一番よく見えます。驚いたことに! これらのいずれかを使用したことがある場合、どのような結果が得られましたか?
4

3 に答える 3

1

あなたが話していることがそこにあるかどうかはわかりません。似たようなものが必要だったので、単純なテキスト置換スクリプトを作成する方が、既存のソリューションを比較して使用方法を学ぶよりも速いと考えました。

このスクリプトは本番環境には対応していません (もっとテストする必要があり、API は奇妙です) が、これを実行する方法の 1 つについてのアイデアが得られるはずです。

設定方法は次のとおりです。


ドキュメントへのテンプレートの保存

テンプレート テキストはtype、「text/javascript」以外の属性を持つスクリプト タグに格納されます。各テンプレートには一意の id 属性があります。

<script id="some_template" type="text/plain">

    a valid template

</script>

ブラウザはこれらをレンダリングすべきではありません。任意の文字を使用でき ( を除く</script>)、エスケープする必要はありません。


プレースホルダー

プレースホルダーは次のようになります{@some_identifier}

<script id="image_template" type="text/plain">

    <a href="{@img_url}"><img src="{@img_url}"></a>

</script>

各プレースホルダーは次のいずれかに置き換えられます。

  • 別のテンプレートから渡された値、
  • テンプレートのコピーを取得するときに JavaScript 関数に渡される引数、または
  • 置換値が見つからない場合は空の文字列。

あるテンプレートを別のテンプレートに含める

@@疑似タグ」には、現在のテンプレートに別のテンプレートのコンテンツが含まれています。

<script id="photo_template" type="text/plain">

    <@@ image_template></@@>

    <div class="photo-caption">{@caption}</div>

</script>

photo_template含まれてい image_templateます。インクルージョンの置換はすべて、プレースホルダーの置換の前に行われるため、およびプレースホルダーphoto_templateも同様です。{@img_url}{@caption}


プレースホルダー置換による包含

これが「ラッピング」の由来です。理想的には、プレースホルダーは、テンプレートのコピーを取得するときに渡される値ではなく、ほとんどの場合、他のテンプレートのコンテンツに置き換えられます。

<script id="missing_photo_template" type="text/plain">

    <@@ photo_template>
        <@ img_url>notfound.png</@>
    </@@>

</script>

missing_photo_templateを含みphoto_template、 の代わりを提供するため{@img_url}、プレースホルダーmissing_photo_templateのみが含まれます。{@caption}


JavaScript

API は今のところ最悪ですが、基本的にメインの名前空間atには と の 2 つの関数がtxtありnodeます。1 つ目はテンプレートのコピーをテキストとして取得し、2 つ目はコピーを要素として取得します (上記の例とは異なり、1 つのルート ノードが必要です)。

ここにあります:

/**

    Atrocious Templates

*/
var at = (function(){

  var rTemplate = /<@@\s*(.*?)>((?:[\w\W](?!<@@))*?)<\/@@>/gm,
      rOption = /<@\s*(.*?)>([\w\W]*?)<\/@>/gm,
      rValue = /\{@(.*?)\}/g,
      rTag = /<(\w+)/i,
      rSpace = /\s+/,
      templates = {},
      doc = document.implementation.createHTMLDocument('');

  /** 

      Inlcude inner templates.

      @private

      @param {string} m0
          The full inclusion text.

      @param {string} m1
          The ID of the included template.

      @param {string} m2
          Values passed to included template.

      @return {string} 

  */
  function includeTemplates(m0, m1, m2) {
    var opts = {};
    m2.replace(rOption, function(m0, m1, m2) { opts[m1] = m2; });
    return txt(m1, opts, true);
  }

  /** 

      Get text contents of a template.

      @private

      @param {string} id
          The ID of the template.

      @return {string} 

  */
  function get(id) {
    if (templates[id]) return templates[id];
    var last, t = document.getElementById(id).innerHTML;
    while (last != t && (last = t)) t = t.replace(rTemplate, includeTemplates);
    return (templates[id] = t);
  }

  /** 

      Get a text copy of a template.

      @param {string} id
          The ID of the template.

      @param {Object.<string|function ():string>} options
          Properties of this object will replace placeholder tokens.
          Each property can be either a string, or a function which 
          returns a string.

      @param {boolean=} noStrip
          By default, placeholders for which no replacement text is 
          found are removed. Setting this to `true` overrides that
          behavior, leaving non-replaced placeholders intact. 

      @return {string} 

  */
  function txt(id, options, noStrip) {
    if (!options) options = {};
    return get(id).replace(rValue, function(m0, m1) {
      var v = options[m1];
      return noStrip && !v && m0 || v && (v.call ? v() : v) || '';
    });
  }

  /** 

      Get a node copy of a template.

      @param {string} id
          The ID of the template.

      @param {Object.<string|function ():string>} options
          Properties of this object will replace placeholder tokens.

      @return {string} 

  */
  function node(id, options) {
    var text = txt(id, options),
        root = text.match(rTag)[1];
    doc.open; doc.write(text); doc.close();
    return doc.getElementsByTagName(root)[0];
  }

  // exports

  return { txt: txt, node: node };

}());

繰り返しますが、これはあまりテストされていないため (正常に動作しているように見えますが)、本番環境で使用することはお勧めしませんが、希望することを達成する方法についていくつかのアイデアが得られることを願っています.

于 2012-04-20T05:50:26.470 に答える
0

handlebarjs.com を見てみてください。サーバーとクライアントの両方で使用しています。

于 2012-11-05T10:51:51.617 に答える
-1

質問は古いかもしれませんが、Mustache はパーシャルをサポートしていませんか?

http://mustache.github.io/mustache.5.html

...このように、文字通り真実ではありませんが、パーシャルをインクルードまたはテンプレート展開と考えたいと思うかもしれません。

たとえば、このテンプレートと部分:

base.mustache :

<h2>Names</h2> {{#names}}   {{> user}} {{/names}}

user.mustache :

<strong>{{name}}</strong>

1 つの拡張されたテンプレートと考えることができます。

<h2>Names</h2> {{#names}}   <strong>{{name}}</strong> {{/names}}
于 2014-12-18T20:15:27.880 に答える