EJSで使いやすい構文まとめ

今回はNode.jsのパッケージ「EJS」で使いやすい便利な構文をまとめてみました。

なお、glup-ejsでビルドしたことを想定しています。

 

EJSでできること

EJSでできることはざっくりまとめるとこんな感じです。

  • 変数、配列、オブジェクトなどの宣言とその処理
  • HTMLへ結果を出力
  • ループや条件分岐など
  • 外部ファイルの読み込み、パラメーターの引き渡しなど

 

ではEJSで使いやすい構文を紹介します。

 

<% %>に関連する

<% %>

このタグの中はJavaScriptと同じになります。この時点ではHTMLには出力されません。

<% var myParam = 'Hello! EJS!'; %>

 

<%= %>

中にある変数をエスケープを含めて展開します。

「<」や「>」がエスケープされて出力されるのでHTMLタグ等は<%- %>を使う

EJS

<div><%= myParam %></div>

 

HTML

Hello! EJS!

 

<%- %>

中にある変数をエスケープなしで展開します。

EJS

<% var para = '<p>Hello EJS!</p>'; %>
<div><%= para %></div>
<div><%- para %></div>

 

HTML

<div>&lt;p&gt;Hello EJS!&lt;/p&gt;</div>
<div><p>Hello EJS!</p></div>

 

<%# %>

内側がコメントアウトされます。コメントはHTMLに出力されることはありません。

EJS

<%# EJS Comment! %>
<!-- HTML Comment! -->

 

HTML

<!-- HTML Comment! -->

 

include()

第一引数に読み込みたいEJSファイルまでのパスを渡します。基準は現在のディレクトリ。また、拡張子の.ejsは省略可能です。

第二引数には第一引数のEJSファイルに渡すパラメーターを指定します。

<%- include('./_partial', {param:'param'}) %>

 

また、似たようなものでincludeディレクティブがありますが、これは以下のようなデメリットがあるのであまり使いやすくありません。

  • パラメーターを渡せない
  • パスを変数から作成することができない

なのでinclude()を使った方が便利ということになります。

 

変数のスコープと受け渡し

include()したファイルへ変数を渡すには次の2つの方法があります。

  • include()の第二引数として渡す
  • グローバル変数としてvarをつけずに変数宣言をする

ただし、ファイル間でもローカル変数の共有はできません。。

 

include()の第二引数をして渡す

include()の第二引数として変数を渡す場合はオブジェクトのキー名が、子ファイルのローカル変数名と一致するようにしてください。

また子ファイルにに渡していないキー名を参照しようとしてもエラーになってしまうので注意してください。

 

one.ejs

<% var myData = {head:'Head text', body:'Body text'}; %>
<% include('two.ejs', {var1:'hoge', data:myData}); %>

 

two.ejs

<section class="<%= var1 %>">
  <h2><%= data.head %></h2>
  <p><%= data.body %></p>
</section>

 

キー名があるかどうか分からない場合は、変数がundefinedの時に初期値をセットするようにするとエラーを回避できます。

if (typeof var1 === 'undefined') { var var1 = ''; }
if (typeof data === 'undefined') { var data = {head:'default', body:'default'}; }

<section class="<%= var1 %>">
  <h2><%= data.head %></h2>
  <p><%= data.body %></p>
</section>

 

ループ処理

for

処理の書き方自体はJavaScriptと同じですね。

<% for (var i = 0; i < 10; i++) { %>
<p>このループは<%= i+1 %>回目です。</p>
<% } %>

 

while

こちらも書き方はJavaScriptと同じです。

<% var counter = 1; %>
<% while (counter <= 10) { %>
<p>このループは<%= counter %>回目です。</p>
<% counter++; %>
<% } %>

 

array.foreach()

配列を順番に取り出すならこの書き方が一番汎用性が高いです。

<% var ary = ['アイテム1', 'アイテム2', 'アイテム3']; %>
<% ary.forEach(function (value, key) { %>
<p><%= key %>: <%= value %></p>
<% }); %>

 

for…in、for…of

for…inやES6のfor…ofも使用できます。ただし、for…inは順番が不確定なのであまり使わないようが良さそうです(特にテンプレート)

<% var ary = ['アイテム1', 'アイテム2', 'アイテム3']; %>

<% for (var key in ary) { %>
<p><%= ary[key] %></p>
<% } %>

<% for (var item of ary) { %>
<p><%= item %></p>
<% } %>

 

条件分岐

if…else

JavaScriptrとおなじようにif…elseも使えます。

<% if (data.type === 'type1') { %>
<p class="type1">This template is for type1.</p>

<% } else if (data.type === 'type2') { %>
<p class="type2">This template is for type2.</p>

<% } else { %}
<!-- else -->
<% } %>

 

switch

switch分も同じくJavaScriptのようにかけますが、<% %>で途中で分断してしまうと動かないので注意。

動く書き方↓

<% var text = ''; %>
<% var state = 0; %>
<% switch ( state ) {
  case 0:
    text = 'case0';
    break;
  case 1:
    text = 'case1';
    break;
} %>
<p><%= text %></p>

 

動かない書き方↓

<% var text = ''; %>
<% var state = 0; %>
<% switch ( state ) { %>
<% case 0: %>
  <p>case0</p>
<% break; %>
<% case 1: %>
  <p>case1</p>
<% break; %>
<% } %>

 

関数化して再現性を高める

ひとまとまりのHTMLテンプレートは関数化して再利用できるようにしていきます。ループや条件分岐を多用するとどんどんネストが深くなって面倒なことになるので、ときどき関数にくくり出すと整理しやすいですね。

<%# generateItem関数を定義 %>
<% var generateItem = function(name, dataList){ %>
  <ul class="<%= name %>">
    <% dataList.forEach(function (dataItem, index) { %>
      <li class="<%= name + '__' + index %>"><%= dataItem %></li>
    <% }); %>
  </ul>
<% }; %>

<%# ここで定義した関数を実行 %>
<%- generateItem('item-list', ['ホーム', '新着情報', '会社概要']); %>