20

次のように、一部の EJS コードで Javascript 変数 (フロントエンドで定義) を使用する必要があります。

var selected = 1;
<% for (var i=0; i < supplies.length; i++) { %>
    if (i == selected) {
        console.log(supplies);    
    }
<% } %>

EJS、Express.js、および socket.io を使用しています。メッセージを Node.js サーバー インスタンスに送信することで、Javascript 変数を EJS 変数に変換できますが、それはばかげています... EJS 内で Javascript 変数を使用する方法はありますか?

編集: ユーザーがドロップダウン メニューからアイテムを選択した後、javascript 配列であるサプライにアクセスしたいと考えています。彼がこの項目を選択すると、上記のコードを含む JavaScript 関数が何らかの EJS にアクセスする必要があります。そのため、EJS で通常の Javascript 変数を使用する必要があります。

4

1 に答える 1

51

JavaScript 変数をテンプレートに渡すことはできますか? :

テンプレートにさらにデータを取得して再レンダリングすることは可能ですが、考えている方法ではなく、サーバーに別のリクエストを行う必要はありません (HTML を取得するのではなく、データを取得する場合を除きます)。

解決:

この質問は、詳細がわからないと答えるのが難しいため、選択した値を EJS テンプレートに渡す理由についていくつかの仮定を立てます。お客様の目標に関する限られた情報でお答えできるよう最善を尽くします。

ユーザーがクリーニング用品の選択など、ページ上で何らかのアクションを実行しているようで、ユーザーが選択した要素に基づいてデータを異なる方法でレンダリングしたいと考えています。これを行うには、テンプレートを再レンダリングし、選択された要素に特定のクラスを適用するビュー ヘルパーを使用して、どの要素が選択されているかを識別するデータを渡します。

以下は、ビュー ヘルパーを使用してクラスが追加された、変更されたcleaning.ejsテンプレートです。

クリーニング.ejs:

<script>
// NOTE: even if uncommented, JavaScript inside a template will not run.
//    var selected = 1;
</script>
<h1><%= title %></h1>
<ul>
    <% for(var i=0; i<supplies.length; i++) { %>

        <li>
            <!-- apply a class to the selected element -->
            <a class='<%= supplies[i].selected %>' href='supplies/<%= supplies[i].value %>'>
                <%= supplies[i].value %>
            </a>
        </li>
    <% } %>
</ul>    

レンダリングされた HTML は次のようになります。

<script>
    /** NOTE: Script blocks will not fire in rendered templates. They are ignored
    //    var selected = 1;
</script>
<h1>Cleaning Supplies</h1>
<ul>


        <li>
            <a class="" href="supplies/Broom">
                Broom
            </a>
        </li>


        <li>
            <!-- Note the selected element -->
            <a class="selected" href="supplies/mop">
                mop
            </a>
        </li>


        <li>
            <a class="" href="supplies/Hammer">
                Hammer
            </a>
        </li>

</ul>

このビューは、次の JavaScript コードを使用してレンダリングされました。

// modified data structure so that array of supplies contains objects
 // with the name of the item and whether or not it's selected.
data = {
    "title":"Cleaning Supplies",
    "supplies":[
        {
            "value":"Broom",
            "selected":""
        },
        {
            "value":"mop",
            "selected":"selected"
        },
        {
            "value":"Hammer",
            "selected":""
        }
    ]
};

// pass data into template and render
var html = new EJS({url: 'cleaning.ejs'}).render(data);

// add HTML to the DOM using a <div id="container"></div> wrapper.
document.getElementById("container").innerHTML = html;

ご覧のとおり、supplies[i].selected は、選択されたクラスを、データ構造で選択済みとしてマークされた要素に適用します。配列自体の値ではなく、i 番目の配列項目のオブジェクトにアクセスするように、href 値を変更しました。

選択した項目が変更されたら、データ変数を変更し、EJS テンプレートを再レンダリングして、DOM に追加するだけです。

この CSS を HTML ドキュメントの head に配置すると、次のような内容が表示されます。

<style>
    .selected { color:red; }
</style>

選択した要素のデモ (赤)


テンプレートの JavaScript が実行されない理由:

JavaScript 値を操作したり、EJS テンプレート内で JavaScript 値を使用したりするために使用しようとしている方法は機能しません。これは主に、JavaScript が実行されるときのコンテキストに関係しています。

EJS テンプレートはクライアント側でコンパイルされると考えるのは正しいことです。ただし、ビュー ヘルパーの JavaScript は、グローバル コンテキストの JavaScript とは無関係に実行されます。ejs.js のソース コードを見ると、プロセスで eval が使用されているように見えます。

さらに、EJS はレンダリングされた HTML を文字列として返します。EJS のドキュメントでは、レンダリングされたテンプレート文字列を innerHTML を使用して DOM に挿入するように指示されています。

document.getElementById("container").innerHTML = html;

使用しているビュー テクノロジに関係なく、一部のブラウザーの JavaScript に関する基本的な真実の 1 つは次のとおりです。 一部のブラウザーは、innerHTML を使用して DOM に追加されたブロックを評価しない場合があります。<script>

つまり、私のテスト テンプレートで、選択した値をコンソールに出力するためのスクリプト タグを追加しようとすると、スクリプト ブロックが追加されていることがわかりますが、innerHTML の動作方法により、実行されませんでした。

サンプル テンプレートは、innerHTML を使用して追加すると JavaScript が実行されないことを示しています。

 <h1><%= title %></h1>
<ul>
    <% for(var i=0; i<supplies.length; i++) {  %>
       <span id="selected"></span><script>console.info('test <%= i %> = <%= supplies[i] %>');</script>            
        <li>
            <a href='supplies/<%= supplies[i] %>'>
                <%= supplies[i] %>
            </a>
        </li>
    <% } %>
</ul>

レンダリングされた HTML:

以下に示すように、console.log ステートメントが HTML に含まれています。ただし、innerHTML を使用して追加すると、それらは起動しません。

ビュー テクノロジを使用する場合のアプローチは、その使用をビューのレンダリングのみに制限することです。ロジックを「通常の JavaScript」に保持します。

<h1>Cleaning Supplies</h1>
<ul>

       <span id="selected"></span><script>console.info('test 0 = Brrom');</script>            
        <li>
            <a href='supplies/Brrom'>
                Brrom
            </a>
        </li>

       <span id="selected"></span><script>console.info('test 1 = mop');</script>            
        <li>
            <a href='supplies/mop'>
                mop
            </a>
        </li>

       <span id="selected"></span><script>console.info('test 2 = Hammer');</script>            
        <li>
            <a href='supplies/Hammer'>
                Hammer
            </a>
        </li>

</ul>

その他の例とドキュメントは、 Google Code Embedded JavaScriptサイト の EJS テンプレートにあります。

于 2012-05-27T23:56:17.073 に答える