はじめに
Riot.js
ではeach
属性を使って簡単にループ処理を書けるのですが、地味にこけるポイントだと思いますので書きました。現時点のRiot.jsの最新バージョンは2.4.1
です。
まずは単純な配列でeach
何はともあれコードを見ましょう。
<app>
<!-- layout -->
<ul>
<li each="{ key in tasks }">{ key }</li>
</ul>
<!-- javascript -->
<script>
this.tasks = ['hoge','fuga','piyo'];
<script>
</app>
結果は以下です。
// hoge
// fuga
// piyo
何の変哲もなく、ただの文字列配列をeach
で出力しているだけですね。ちなみにeach={ tasks }
と書くと、何も出力されません。
キー無しのオブジェクト配列でeach
そもそもこの呼び方が正しいのか否かは目を瞑っていただいて、先程よりちょっと中身が複雑な配列の場合のコードを見てみましょう。
<app>
<!-- layout -->
<ul>
<li each="{ tasks }">{ body }</li>
</ul>
<!-- javascript -->
<script>
this.tasks = [
{'body': 'hoge'},
{'body': 'fuga'},
{'body': 'piyo'}
];
</script>
</app>
結果は以下です。
// hoge
// fuga
// piyo
今度は配列の要素それぞれがオブジェクトになっており、それぞれのキーはbody
で統一されています。値を出力する際は{ キー }
を指定すれば表示されます。
上記のlayout
部分を以下のように書くと、各オブジェクトのインデックスも表示できます。
<!-- layout -->
<ul>
<!-- ここの 'task' と 'i' の順番が重要! -->
<li each="{ task, i in tasks }">{ i }: { task.body }</li>
</ul>
結果は以下です。
// 0: hoge
// 1: fuga
// 2: piyo
キー有りのオブジェクト配列の場合
ある意味これが本題です。ここでコケました。
<app>
<!-- layout -->
<ul>
<li each="{ task, key in tasks }">{ key }: { task.body }</li>
</ul>
<!-- javascript -->
<script>
this.tasks = {
'a': {'body': 'hoge'},
'b': {'body': 'fuga'},
'c': {'body': 'piyo'}
};
</script>
</app>
結果は以下です!
// [object Object]:
// [object Object]:
// [object Object]:
はい。キー無しのオブジェクト配列と同じように記述すると、思ったように値を表示できないんですよ。。。これを期待通りに表示するには、layout
部分のkey
とtask
を先ほどとは逆に書きます。
<!-- layout -->
<ul>
<!-- 'task' と 'key' の順番がさっきとは逆! -->
<li each="{ key, task in tasks }">{ key }: { task.body }</li>
</ul>
もちろん結果は以下です。
// a: hoge
// b: fuga
// c: piyo
2016/12/08 追記
上記はv3にて修正され、反転しなくても良くなりました。
ループのネストについては別の方が記事を書いてくださっているので、そちらを参照ください。(「参考」の二つ目の記事です)
※ もう一つ注意点として、eachの中でopts
変数の中身を展開しようとするとできないので気をつけてください!
おわりに(読まなくてもいいです)
each
でループについての投稿記事って案外なくて書きましたが、知っている方からしたら常識かもしれませんが、このレベルの記事もないくらい、まだまだRiot.js
って使われてないんですかね。もっと皆さんに使っていただきたいと思う今日このごろです。