JavaScript
Node.js
swig
vue.js

【Memo】mustache記法のテンプレートエンジンswigでVue.jsを使う時は、デリミタをエスケープする必要がある

More than 1 year has passed since last update.

今年一発目の投稿になります。
仕事で初めてVue.jsを使おうと思い、案件に組み込もうとしたらdata部分が出力されないという状況でハマったのでメモしておきます。

なぜ出力されなかったのか

結論としては、テンプレートエンジン内のVue.jsの{{ mustache }}は、swigの文法として認識されるため出力されません。※swigのdataとしては定義していないため出力されなかった

Vueとして認識させるには、テンプレート内に{% raw %} 〜 {% endraw %}で括る必要があるようです。

swigの記事ではなく、 twigテンプレートエンジンでvue.jsを使うとデリミタがコンフリクトする。を参照して対応してみました。

自社の開発では、テンプレートエンジンswigを使ってコーディングしています。このswigでは {{ mustache }}という記法で書きます。

雛形のテンプレートをベースにページごとにコーディングしていきます。
この時に雛形に記述されている{{ title }}などをページ単位で宣言して出力させます。

Vue.jsでv-forで表示させるには、以下のpage.htmlで記述した{{ todo.text }}を記述します。

Vue.jsのソースコードを {% raw %} 〜 {% endraw %}で括ることで{{ mustache }} を通常の文字列として認識させることができVue.jsとして認識させることができます。

default.html
<!-- 雛形テンプレート -->
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
<meta name="description" content="{{ description }}">
<meta name="keywords" content="{{ keywords }}">
</head>
<body class="{{ page }}">
<main>
{{ contents | safe }}
</main>
</body>
</html>
page.html
---
layout: default.html
title: "ページタイトル"
description: "ページの説明がはいります。"
keywords: "キーワード,キーワード"
page: "page"
---

<h1>Vue.jsを表示させる v-forでdataを表示させた例</h1>
{% raw %}
<div id="app">
  <ol>
    <li v-for="list in lists">
      {{ list.text }}
    </li>
  </ol>
</div>
{% endraw %}
app.js
var app;
app = new Vue({
  el: '#app',
  data: {
    lists: [
      { text: 'JavaScript' },
      { text: 'Vue.js' },
      { text: 'swig' }
    ]
  }
});

ソースはサンプルですが、上記のような形で対応する必要があるようです。
今回はswigでしたが{{ mustache }}記法のテンプレートエンジンであれば同じような状態になると思われるので、きちんと除外させることがチェックポイントだと思います。

  • Django、Jinja2、Twig など

実務では、違う問題かと思って色々調べてドハマリしてしまいました。
なんで?この環境だけ表示がされないのだろうと思ったら、今の環境と他の環境との違いをきちんと俯瞰してみることが大切ですね。。

初歩的なことですが、分からずハマるポイントだと思うのでメモしておきます。

参考記事