Mustache.js: 親スコープへのアクセス

作成日 2014年12月11日  ·  18コメント  ·  ソース: janl/mustache.js

親スコープへのアクセス

考慮して:

node = {
  id: 1,
  children : [
      { id : 2 },
      { id : 3 }
  ]
}

そして次のテンプレート:

{{ id }} {# will output node.id #}
{{#children}}
    {{children.id}}  {# will output node.children[i].id #}
    {{id}}  {# will also output node.children[i].id #}
{{/children}}

現状では、親プロパティにアクセスする必要がある場合があります(たとえば、ネストされたノードモデルの場合)。
「../」を使用して親スコープを取得するように簡単に実装できます

元 :

{{ id }} {# will output node.id #}
{{#children}}
    {{children.id}}  {# will output node.children[i].id #}
    {{id}}  {# will also output node.children[i].id #}
    {{ ../id }}  {# will output node.id #}
{{/children}}

それを達成するために:

  Context.prototype.lookup = function (name) {
    var cache = this.cache;

    var value;
    if (name in cache) {
      console.log(name + ' found');
      value = cache[name];
    } else {
      var context = this, names, index;

      while (context) {
        if (name.indexOf('.') > 0) {
          value = context.view;
          names = name.split('.');
          index = 0;

          while (value != null && index < names.length)
            value = value[names[index++]];
        } else if(name.match(/^\.\.\//)) {
          name = name.replace(/^\.\.\//, '');
        } else {
          value = context.view[name];
        }

        if (value != null)
          break;

        context = context.parent;
      }

      cache[name] = value;
    }

    if (isFunction(value))
      value = value.call(this.view);

    return value;
  };
Future Plugin

最も参考になるコメント

右。 ハンドルバーをすっかり忘れてしまいました。

ユーザーをハンドルバーに負けさせます。
これは、許容できる設計上の決定です。

全てのコメント18件

これはmustacheの仕様には含まれていませんね。 これに対する回避策はありませんか? これまで誰もこの制限にぶつかったことがないことに驚いています。

親スコープ内のものにアクセスする必要がある場合が多いことに同意します。 私の実用的なアプローチは、常にあいまいなプロパティ名を避けることでした。 それは私にとって長い間働いてきましたが、それはしばしば奇妙なオブジェクトをもたらします。

一方、ハンドルバーの経験について言えば、 この機能があると、人々が狂った絡み合った親スコープの解決策を作成するように誘惑する可能性があります。 {{../../../id}}は、 {{movieId}}よりも把握するのが非常に困難です。

「../」を使用すると読みにくくなる可能性があるのは事実です。 ただし、逆に、camlをローカルスコープに含めることができるため、camlを使用して親を解決することはできません。 さらに、親にアクセスするためのキーワードを定義することは、私が思うに口ひげの哲学を尊重しません。

率直に言って、ディレクトリ表現を使用するよりも単純で優れたアイデアを思いつくことはできませんでした。

ええ、あいまいなプロパティ名を避けることは、より読みやすく/冗長なテンプレートにもつながります。 しかし、なぜこの機能を好む人がいるのか理解しています。

mustache.jsの内部動作を変更して、目的の機能を追加する別のパッケージを作成するのはどうですか? プラグインのようなものです。

正直なところ、プラグインまたはプラグインを経由しない限り、これが実際に発生することはありません。 そして、プラグインAPIは今のところ優先事項ではないようです。

私はこれについてもう少し考えていました...

Mustacheの哲学は、データをそのままレンダラーに渡すのではなく、事前にビューに「準備」することだと思います。 次に、ノードにparentIdプロパティがあります。

また、より詳細な変数を持つテンプレートを読み、維持するのも簡単です。

{{ id }}
{{#children}}
    {{children.id}}
    {{id}}
{{/children}}

前と後

{{ nodeId }}
{{#children}}
    {{ nodeId }}
    {{ parentId }}
{{/children}}

関連: http

@bobthecowを召喚して申し訳ありませんが、私はいつもあなたの口ひげの知恵に感謝しています:smile :)

あなたはすでに、すべてのもののニーズが最初のテンプレートに示す問題を解決するためにやることが一時オブジェクトでデータをラップする、されるまで行くことができます{node: ... } 、とテンプレートラップ{{#node}}...{{/node}}当時と{{node.id}}部分は機能します。 既存のデータをそのように変更する必要はありません(そして変更しません)。テンプレートをto_html()として、両方の「JIT」を追加できます...

パッチのある回避策のように感じます。 また、外層のエンベロープラップによって解決できる単純な2レベルモデルでのみ機能します。 しかし、モデルがより深い場合はどうなりますか? それはジャグリングを感じます。

多くの場合、下位のデータレイヤーから取得したモデルをバインドする必要があり、私の仕事はそれを提示することです-インフラストラクチャから取得した形式に関係なく。 ここでの命題は、モデルを再帰的にずっと深く、見栄えのする状態に変換する必要があるということです。ここでは、 redable property namesと見なされます。
これは現実に都合よく合わない...
はい、そうです、それはテンプレートをモデルと結合します。 しかし、具体的なモデルルールと組み合わせていないテンプレートを見せてもらえますか? すべてのテンプレートは、定義上、定義されたモデルをレンダリングするために作成されています。
別のレイヤーは、定義のレイヤーを1ステップ戻し、翻訳レイヤーを必要とします。これは、面倒で、常に必要なわけではありません。

私見、私はツールが意見のルールを課すのではなく、ユーザーに選択を任せるべきだと思います

読者のために、 @ rndmeが示唆していることの例:

const Mustache = require('mustache')

var view = {
  node: {
    id: 5,
    children: [ { id: 6 }, { id: 7 } ]
  }
}

const template = `
{{#node}}
  children:
  {{#children}}

    id: {{ id }}
    parentId: {{ node.id }}
  {{/children}}
{{/node}}
`

const output = Mustache.render(template, view)
console.log(output)

  children:

    id: 6
    parentId: 5

    id: 7
    parentId: 5

次のテンプレートの使用は、 latest時点では機能しませんが、_動作するはずです_、imo。

const template = `
  children:
  {{#node.children}}

    id: {{ id }}
    parentId: {{ node.id }}
  {{/node.children}}
`

はい、そうです、それはテンプレートをモデルと結合します。 しかし、具体的なモデルルールと組み合わせていないテンプレートを見せてもらえますか? すべてのテンプレートは、定義上、定義されたモデルをレンダリングするために作成されています。
別のレイヤーは、定義のレイヤーを1ステップ戻し、翻訳レイヤーを必要とします。これは面倒で、常に必要なわけではありません。

Afaik、Mustacheの哲学は常に、テンプレートに渡されるビューを生成することでした。モデルを直接渡すことはありません。

@osher上記のヒント/トリックでは簡単に解決できない例を教えてください。

後でスニペットを提供しようとしますが、基本的には、3つのレベルをネストすると、中間レベルをラップできないため機能しません。ソースを処理済みのビューに変換する必要があります。
ラップされたトップレベルにアクセスすることはできますが、ミドルレベルの解決策はありません。

たとえば、ルートレベル、パスレベル、動詞レベルがあるSwaggerドキュメントを取り上げます(さらに多くのレベルがありますが、ここで停止します)。 各レベルでは、カスタムディレクティブ( x-uses )を指定できます。これは、実装レイヤーのDIディレクティブです。

このSwaggerドキュメントからHTMLドキュメントを生成するとします。
各操作ハンドラー(動詞レベル)に対して、受け入れるDIと、それを継承するレイヤーを指定するフラットテーブルが必要です。
すべての情報はSwaggerドキュメントに固有のものですが、問題が発生しています。

次。
mustacheを使用して、操作のデフォルト応答に基づいて模擬応答を返すドキュメントで説明されているAPIを実装するコードを生成してみてください。
モック応答を実際のロジックに置き換えるために来る実装開発者がDIコンテキストで何を期待すべきかを説明し、それを取得するレベルについて具体的に説明するドックレットを生成してみてください。
同じ...

従来のHTML生成ではありません-そうです。 しかし、口ひげはHTML専用だと誰が言ったのでしょうか。 これはテンプレートエンジンであり、コード生成は通常、このようなテンプレートエンジンを使用して実装されます;)

モデルを直接渡すことはありません。

これは、制限/制限ではなく、ユーザーの選択である必要があります

もう1つ例を挙げましょう。秘密のタレを裏切らずにやってみます。

戦略ゲームでプレーヤーが所有する資産を記述するツリーデータ構造を想定します。
ツリーは、たとえば次のように約5レベル進む可能性があります。
Aliance -> Empire -> City -> Army -> Troops

各レベルは、たとえば、修正ボーナス、または攻撃ボーナス、防御ボーナス、健康ボーナスなどを提供する場合があります。
同じ統計に対応する修飾子は、すべてのレベルで同じ名前で記述されます(主に再帰的に計算されるため)。
テンプレートエンジンを使用して、最下位レベルに存在するが戦闘を収集する軍隊の戦闘統計を表示することにより、プレイヤーが特定のチャレンジに理想的な軍隊を選択するのに役立つ戦闘シミュレーターを提示する必要がありますツリー全体で同じ属性名で名前が付けられている修飾子。
これは_非常に_単純化されていますが、他のツールが中間の翻訳レイヤーを必要とせずに非常に簡単に問題を解決したという実話に基づいています。

難しさを追加します。軍隊が同盟レベルの機動部隊に割り当てられることがあります。
Alliance -> Rally -> Troops
ツールは十分に汎用的(単純な再帰的)であり、具体的なレベルに依存しないようにする必要があります。

私は口ひげがパーシャルと呼ぶものでそれを解決しましたが、口ひげを使用しなかっただけです...

@osherは言った:

これは、制限/制限ではなく、ユーザーの選択である必要があります

口ひげに意見があることは間違いありません。 「ロジックレステンプレート」の哲学は、テンプレートに多くの制限を課します。その事実は、レンダリングのためにテンプレートに渡す前に、データ/モデルの準備を必要とすることがよくあります。 これがニーズに合わない場合は、ハンドルバーlodash.templateなど、より良い代替手段がいくつかあります。

右。 ハンドルバーをすっかり忘れてしまいました。

ユーザーをハンドルバーに負けさせます。
これは、許容できる設計上の決定です。

@osherが「それは許容できる設計上の決定だ」と言ったとき、皮肉を言っていたと確信していますが、このトピックは2016年から放棄されています。どうなっているのでしょうか。 この質問は、このJavaScriptリポジトリとメインリポジトリで回避されているようです。
https://github.com/mustache/mustache.github.com/issues/103

私は、親スコープを参照できることは論理がなく、口ひげの理想を妨げるべきではないと思います。

先頭の「../」のような記号でルートスコープに常にアクセスできるというアイデアが好きです。

Mustache.render('{{a1}}{{#a}}{{b.c}}{{../a1}}{{/a}}',{"a":{"b":{"c":"x1"}},"a1":"x2"})
"x2x1"

これで「x2x1x2」をレンダリングしたいのですが、それが機能しないため、最後のレンダリングは省略されています。
JSONPathのようなものを使用することをお勧めすると思いました: https ://goessner.net/articles/JsonPath/index.html#e2ただし、XPath for XMLとは異なり、親演算子を推奨/実装していません。これは私が望んでいたことです。にとって。

おそらく、Mustacheはハンドルバーとの互換性を維持し、親コンテキストに../構文を使用しようとする可能性がありますか?

AFAIK、ハンドルバーはJSのみですが、口ひげは多くの環境、たとえばPHPで同じ構文を使用します。 口ひげの構文を変更したい場合は、他のすべての非js実装に同じことを行うように説得する必要があります。 背の高い注文。 さらに、JSコードを変更する際に、「1レベル」上げるのは問題があることがわかりましたが、フォーク。これは、実装が非常に

これについて何か?

ドット表記がオプションである状況については、ドキュメントとスタイルの推奨事項も必要です。

view = { wrap: { txt: "test" } };
{{#wrap}}
  {{wrap.txt}} {{! Should I use this?}}
  {{txt}} {{! Or this?}}
{{/wrap}}

詳細はこちら: https

このページは役に立ちましたか?
0 / 5 - 0 評価

関連する問題

connor11528 picture connor11528  ·  3コメント

kuldeepdhaka picture kuldeepdhaka  ·  9コメント

amper5and picture amper5and  ·  5コメント

zekth picture zekth  ·  18コメント

funston picture funston  ·  7コメント