新しい日記

新しい日記

ejs で json からデータを取り込む

ejs は embeddedjavascript というテンプレートエンジン。
gulp 用のパッケージもあるよ。

www.npmjs.com

HTML に組み込むような書き方なので、デザイナーさんなどと共有しやすいし、学習コストが低くて気に入っています。
外部ファイルの include や 変数の呼び出し、ループなど、はもちろん js で出来ることは(たぶん)全部出来る。
以下、外部ファイルの head を読み込んで、見出しに変数を入れ、配列をループさせる簡単な例です。

<% var title = "見出し1", array=["hoge","fuga","poyo"] %>
<html>
<head>
  <% include head %>
</head>
<body>
  <h1><%= title %></h1>
  <ul>
    <% for(var i=0;i<array.length;i++){ %>
    <li><%= array[i] %></li>
    <% } %>
  </ul>
</body>
</html>

出力はこんなかんじ

<html>
<head>
  <meta charset="UTF-8">
  <meta name="description" content="ejs のサンプルです。" />
  <link rel="stylesheet" type="text/css" media="all" href="style.css" />
<title>サンプル</title>
</head>
<body>
  <h1>見出し1</h1>
  <ul>
    
    <li>hoge</li>
    
    <li>fuga</li>
    
    <li>poyo</li>
    
  </ul>
</body>
</html>

include とか出来るだけでも十分っていう場合もあるけど、せっかくなんでデータを取り込んでループさせたりとかしたいですね。
今回私は一週間分の違う料理とその材料を記載したデータを作りましたので、それを gulp + ejs + json でテンプレートに取り込むということをしました。

f:id:tttttahiti:20151016155213j:plain

こんなかんじのイメージです。
ポイントとしては、料理の写真、説明文、材料がユニークな値になり、材料の数も可変ということです。

用意するのは

  • gulp
  • template.ejs
  • data.json

説明を容易にするため、各種ファイルは全て gulp の作業ディレクトリ上にあるということで。
gulpfile.js はこんなかんじ。

var gulp = require('gulp');
var ejs = require('gulp-ejs');
var jsonData = require('./data.json');

gulp.task('build', function(){
  return gulp.src('./templates.ejs')
  .pipe(ejs({
    jsonData: jsonData //jsonData に data.json を取り込む
  }))
  .pipe(gulp.dest('./'));
});

シンプル!json で作ったデータはこんなかんじ。

[
  {
    "daynum": "1",
    "dishname": "おいしいカレー",
    "description": "みんな好きなカレーです。甘口です。",
    "item": [
      {
        "name": "にんじん",
        "amount": "中3本",
      },
      {
        "name": "たまねぎ",
        "amount": "中2玉",
      },
      {
        "name": "じゃがいも",
        "amount": "中3個",
      },
      {
        "name": "カレールー",
        "amount": "4切れ",
      }
    ]
  },
  {
    ...
  },
  {
    "daynum": "7",
    ...
  }
]

excel データを渡されたりなどした場合、これとかで変換するとラクチンです。
次、 template.ejsはこんなかんじ。

<%
var data = jsonData;
%>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" type="text/css" media="all" href="./styles.css" />
  <title>一週間の料理</title>
</head>
<body>
<h1>一週間の料理</h1>
<% data.forEach(function(day){ %>
<section class="dish">
  <h2 class="dish__heading"><%= day.daynum %>日目の料理</h2>
  <div class="dish__image">
    <img src="./img/day<%= day.daynum %>.jpg" alt="<%= day.dishname %>">
  </div>
  <div class="dish__body">
    <p class="dish__name"><%= day.dishname %></p>
    <p class="dish__description"><%= day.description %></p>
    <ul class="ingredients">
      <% day.item.forEach(function(item){ %>
      <li class="ingredients__item">
        <p class="ingredients__name"><%= item.name %></p>
        <p class="ingredients__amount"><%= item.amount %></p>
      </li>
      <% }) %>
    </ul>
  </div>
</section>
<% }) %>
</body>
</html>

ポイントは、 forEach 文で各配列 or オブジェクトを操作する形にするっていうところです。

for(var i=0;data.length;i++){
...
}

のような記法だと、なぜだか data[i].description などが読み込めません…!
出力すると以下のようになるはずです。

<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" type="text/css" media="all" href="./styles.css" />
  <title>一週間の料理</title>
</head>
<body>
<h1>一週間の料理</h1>

<section class="dish">
  <h2 class="dish__heading">1日目の料理</h2>
  <div class="dish__image">
    <img src="./img/day1.jpg" alt="おいしいカレー">
  </div>
  <div class="dish__body">
    <p class="dish__name">おいしいカレー</p>
    <p class="dish__description">みんな好きなカレーです。甘口です。</p>
    <ul class="ingredients">

      <li class="ingredients__item">
        <p class="ingredients__name">にんじん</p>
        <p class="ingredients__amount">中3本</p>
      </li>

      <li class="ingredients__item">
        <p class="ingredients__name">たまねぎ</p>
        <p class="ingredients__amount">中2玉</p>
      </li>

      <li class="ingredients__item">
        <p class="ingredients__name">じゃがいも</p>
        <p class="ingredients__amount">中3個</p>
      </li>

      <li class="ingredients__item">
        <p class="ingredients__name">カレールー</p>
        <p class="ingredients__amount">4切れ</p>
      </li>

    </ul>
  </div>
</section>

<section class="dish">
  <h2 class="dish__heading">2日目の料理</h2>
  ...


</body>
</html>

参考記事

qiita.com

qiita.com

aircolor.hatenablog.com