CoffeeScript + less + jade(pug) で riot.js テンプレ


はじめに

CoffeeScript じゃなくES6なんじゃないか~?とか
less じゃなく、sass なんじゃないか~?とか
jade(pug) じゃなく、html で良いんじゃね?とか

いろいろあるとは思いますが…

riot.js を触ろうと思った時に、この組み合わせで作業してて、なかなかこの組み合わせで使ってるのが見つからなかったので自分で作って見ました。

今回は、その紹介。スクラップ・アンド・ビルド、他の構成で作り直したい時には、また作り直します…

と、言う事で、もうすこし、Advent Calendar 的には、日にちの早い段階で書く内容だった気がしますが Riot Advent Calendar 2016 の 21 日目です。

結果から

できてるのが、これです。
作成されるのは、riot.js を含む、bundle.js

script で読み込んで、タグを書けば、html の好きな場所でつかえると言う形にしてます。コンポーネントがこんな簡単に… riot.js すごいって思ったところ。

ただ、こうやってコンポーネント作っていろいろ読み込むと、riot.js がいっぱい入っちゃう感じなので、ちゃんと別々にしておく方法もできるようにしないと…(心覚え)

いまのところ、タグを1つ書くだけのコンポーネントを、1つしか使わないつもりなので、これで間に合ってます

SPA みたいにもできるとは思いますが、jsを1つ読み込んでタグを書くだけで使えると言う形にしたかったので、このような形に。

使い方

npm install
npm start

で、良いと思います。

gulp を使っているので直接使うなら

package.json
  "scripts": {
    "start": "gulp",
    "build": "gulp build",
    "test": "gulp test",
    "clean": "gulp clean"
  }

こんな感じになってます。

test はまだできてない…どうやってするのがいいのかな~と思ったら 19日目 にあったので、今度参考にしようと思います(心覚え2)

npm start / gulp の場合は、ビルドして、ウォッチして、サーバー&ブラウザを起動と言う形でコードを直せば、リロードされます。

watchify は、まだ入れてないです

特殊なタスク

必要に駆られて…タグを作成する時にテンプレートから作れるようにしました。

gulp mktag --name <tagName>

tagName で指定した名前で、テンプレートからタグを作成する環境(coffe,less,jade の各ファイル)を作る。

例) gulp mktag --name tabs

構成

src
├─main
│  ├─public
│  │      index.html
│  │
│  └─riot
│      │  main.coffee
│      │
│      └─sample
│              sample.coffee
│              sample.less
│              sample.tag.jade
│
└─template
        name.coffee
        name.less
        name.tag.jade

riot.js では、hoehoe.tag.html とか1ファイルでまとめて使うこともありますが、やっぱり別々になってた方が良いな~と、別けました。

sample.tag.jade では、sample.coffee と sample.less を include してるだけなので jade ファイル1つでも出来ると思います。

index.html は確認用のhtml

main.coffee で、必要なタグを読み込んで、mount してます。

main.coffee
riot = require 'riot'

require './sample/sample.tag.jade'

riot.mount('*')

ここに、使うタグを全部読み込んでおいた方が良いんだけど、新しく作ったときとか忘れがち

src/template は gulp mktag で作成されるタグの元になるテンプレート(gulp-template使用)

jade(pug)を使った場合の riot.js

jade から pug に変わったみたいですが、まだとりあえず拡張子は jade のまま…

基本的なところ

sample.tag.jade
sample
  div sample
    | Test
    div.name name={ opts.name }
    div.str str={ str }
    div.content content=<yield/>

  input(ref='inputText' onkeyup='{ onInput }' value='{ str }')

jade(pug)を触ったことある人なら、riot.js のガイドとかの html みれば、jade でどの様に書くか想像できると思いますが一応。

タグの属性は、普通に必要な位置で { opts.name }

タグのインスタンス変数とかも同様 { str }

タグで入れ子にされた値 <yield/>

yield タグだからと、思って インデントつけて yield を書いたけど無理でした。

条件

  div(if='{ data > 0 }')
    div ....

ふつーに

ループ

tabs.tag.jade
tabs
  ul
    li たぶ
    li(
      each    = '{ tab, i in tabs }'
      class   = '{ current: currentTab == i }'
      onclick = '{ clickTab }'
    ) { tab }

なんかややっこしいけど、こんな感じにも

less を使った場合の riot.js

スコープを使って、タグごとにスタイルが設定できますね。

その時の書き方 less な場合。

tabs.less
:scope {
  display : block;

  >ul {
    position   : relative;
    list-style : none;
    margin     : .5em 0px;
    padding    : 0px;

    &:after {
      position : absolute;
      content  : "";
      width    : 100%;
      bottom   : 0;
      left     : 0;
      z-index  : 1;
      border-bottom : 1px solid #AAA;
    }

    >li {
      position   : relative;
      display    : inline-block;
      z-index    : 0;
      padding    : 0.25em 0.5em;

      &:not(:first-child) {
        margin     : 0px 0px 0px -1px;
        border     : 1px solid #AAA;
        background : #ECECEC;
        cursor     : pointer;
      }

      &.current {
        background : #FFF;
        z-index    : 2;
        border-bottom-color: #FFF;
        cursor     : auto;
      }
    }
  }
}

ハイライトに less がない? sass はあるぽいのに

CoffeeScript を使った場合の riot.js

tabs.coffee
@currentTab = 0

@tabs = [
  'Foo'
  'Bar'
  'Xyz'
]

@clickTab = (e) =>
  @currentTab = e.item.i

ハンドラとか作るときは、ES6の方が見やすいな~とか思いつつ。

CoffeeScript では、関数作るときに、->=> がありますが、イベントハンドラを作る時は、=>を使わないとダメです。

ダメと言うか使った方が楽、上の例だと、@currentTab のインスタンス変数を、変えてるけど、this @ は、何になるんだっけ?みたいなのが発生するので、=> で書くと、大丈夫。

実際のところ、riot.js だと、@refs を使ってもアクセスできるので、それを使う場合も…と、思ったんだけど、例えば sample の input を以下のようにした。

sample.coffee
@onInput = (e) ->
  @str = @refs.inputText.value

-> で動く…うーむ。

sample.coffee
@onInput = (e) ->
  @str = e.target.value

これでもOK。だけど、riot.js 的には上の @refs を使うのがいい気がするけどどうでしょ。

->=> は、イベントによるのかな?うーむ

みっくすいん

@mixin require '../mixin.coffee'

タグごとにディレクトリつくってるので、その上に mixin 用のファイルを用意して読み込む感じ。

ラスト

テンプレートなので、使い方説明したら終わっちゃうので、それぞれの書き方をサンプル的に書いてみました。

実際に、これを使って作ってるものは、Wikiプラグインで、結構大きなコンポーネントになってて riot.js のタグが100個以上ありそう…まだまだ完成してないです。
こういうのを作るときに、1つのJSファイルで小さくまとまるのは、とても楽だと思ってます。

コンポーネントとして、riot.js のタグが共有できるようになると面白そうです。

この記事のために、ためしに切り出した tabs

riot.js tabs sample

コンポーネントとするなら、引数とかでタブを設定できて、ハンドラも設定できるようにすればいいのかな?