Riot.jsで自分の頭の足りなさをごまかせた話

最近はSPAとかSSRとか流行りですが、バックエンドエンジニアによってはそんなJavaScriptに学習コストを割けないというのも事実だと思います
それに、小中規模のWebサイトでしたらSPAを入れなくても、フレームワークでURL管理したらいいじゃんと思う機会も多いと思います
そういう面倒くさがりな自分に、とっておきのライブラリがありました

# 非常に頭の悪いRiot.jsの使い方
※これやると多分フロントエンドの人に怒られますので、決して真似しないでください

```html+django

{% block content %}
    <sample></sample>
{% endblock %}

{% block javascript %}
  {% compress js %}
    <script>
      var importTest = {{ importTest|safe }}
    </script>
    <script src="{% static "js/iroiro.js" %}"></script>
  {% endcompress %}
  <script src='https://cdnjs.cloudflare.com/ajax/libs/riot/2.3.18/riot+compiler.js'></script>
  <script src="{% static "sample.tag" %}" type="riot/tag"></script>
  <script>riot.mount('sample')</script>
{% endblock %}

```

Djangoのテンプレートであれこれしてますが、基本的にはRiot.jsをコンパイラごと読み込んでるだけです
compressでコンパイルすればいいじゃんと分かる人なら言うと思いますが、~~単純にめんどくさかった~~複雑なことが出来る気がしないので以上の通りになりました
これでも動いてしまうのだから、Riotは偉大です

# Riotのソースコード
適当にデータを加工してHTMLっぽいのに渡すだけです
使用感はReactやAngularよりもJinja2とかの方が近いかもしれません
以下はカレンダーのRiot箇所のコードですが、見た感じだと全然JavaScriptっぽくない感じがすると思います

```html:tenuki.tag
<sample>
  <table>
    <tbody>
      <tr each={ v in cells } class="calendar">
        <td each={ v } class="calendar { class }">
          { name }
        </td>
      </tr>
    </tbody>
  </table>
  <script>
    this.cells = createCell(0);
  </script>
<sample>
```

createCellの中身は以下の通りです

```js:iroiro.js
var createCell = function (v) {

  // 今月の1日をゲットする
  var now_date = new Date();
  var today_date = new Date(now_date.getFullYear(), now_date.getMonth() + v);  // 今月のデータ
  var today_now_date = new Date(now_date.getFullYear(), now_date.getMonth(), now_date.getDate());  // 今日のデータ

  var ts_base = today_date.getTime();  // timestampの作成

  // カレンダーの順番は日曜日からとする
  var calendar_cell = [];
  var calendar_cell_base = [];

  // カレンダーの便利なあれこれの処理
  var calendar = {};
  calendar.week = ["su", "mo", "tu", "we", "th", "fr", "sa"];
  calendar.week_label = ["日", "月", "火", "水", "木", "金", "土"];
  calendar.today_month = today_date.getMonth();

  var one_day = 1000 * 60 * 60 * 24;  // 1日送りする
  // カレンダー処理が終わるまでループさせる
  for (var i=0; i!=calendar.week.length; i++) {
    calendar_cell_base.push({
      "name": calendar.week_label[i],
      "class":calendar.week[i] + " " + "calendar-head"
    });
  }

  // 挿入し、初期化する
  calendar_cell.push(calendar_cell_base);
  calendar_cell_base = [];

  var month_flag = true;  // 次の月を指定された時に、初期設定データが挿入されるのを防ぐ
  var before_week = 0;
  while (true) {
    var date_cell = new Date(ts_base);
    var date_week = date_cell.getDay();  // 曜日の取得
    var date_date = date_cell.getDate();  // 日時の取得

    // 初期データの作成
    if (date_cell.getDate() == 1 && month_flag) {
      // 空セルの挿入
      for (var j = 0; j != date_cell.getDay(); j++) {
        calendar_cell_base.push({
          "name": null,
          "class": calendar.week[j]
        });
      }
      month_flag = false;  // 次の月を指定された時に挿入されるのを防ぐ
    }

    // 月終わりの場合、空セルを挿入してからbreakする
    if (date_cell.getMonth() != calendar.today_month) {
      // 空セルの挿入
      for (var k = 0; k != 6 - before_week; k++) {
        var week_key = k + date_week;
        calendar_cell_base.push({
          "name": null,
          "class": calendar.week[week_key]
        });
      }
      calendar_cell.push(calendar_cell_base);
      break;
    }

    // セルを作る
    calendar_cell_base.push({
      "name": date_date,
      "class": calendar.week[date_week]
    });

    // 土曜日（週終わり）の場合、改行する
    if (date_week == 6) {
      calendar_cell.push(calendar_cell_base);
      calendar_cell_base = [];
    }

    before_week = date_week;  // 前の週の計算をする
    ts_base += one_day;  // 時間を足す

  }

  return calendar_cell
};
```

createCell()で呼び出せるオブジェクトの構造は以下の通りです
[[曜日リスト{class,name},][1段目カレンダー][2段目カレンダー][3段目カレンダー][4段目カレンダー]([5段目カレンダー])]

以上のように、素人でも簡単にHTMLとJavaScriptの分離をさせる事に成功しました
分離させることにより、以下のメリットが生じます

  * デザインの変更がしやすい
  * メンテナンスが楽になる
  * かっこいいコードが書けた気がする

逆に、以下のデメリットも同時に生じます

  * jQueryで最適化するパターンと比べ若干遅い
  * ~~良く考えるとかっこわるい~~

# 最後に
~~バックエンド屋にフロントエンドまでやらせんなDjangoの学習だけで頭一杯なのにNodeとかReactとか詰めると頭が超新星爆発起こしそうなので手抜きしました、許してください何でもしますから~~
もうJavaScriptでフロント部分をあれこれするという無駄から簡単に離れられるので、Riot.jsは優秀だと感じました
Riot.jsを入り口として、将来的にはReactなどに発展してみたいとも思っています