Riot.jsで配列を飛ばしつつ回すと、正しいインデックスが取れない


Riot.jsを使っていろいろ組んでいたのですが、ちょっと想定外の挙動を食らってしまいました。

each

Riotのタグ内では、eachを使って配列を展開することができます(オブジェクトにも使えますが、今回の話題と関係ないので、とりあえずそちらは省略します)。

公式ガイドにも例が上がっていますが、

  • each={ arr }arrの中身をオブジェクトとしてタグ内に展開
  • each={ item in arr }arrの各要素をitemとして取得できる
  • each={ item, i in arr }arrの要素はitem、インデックスはiとして取れる

というようになっています。ただ、実際には最後のものに落とし穴がありました。

配列を飛ばしてみた

Riotのタグ内で直接使える制御構造はeachifだけですが、「eachで回しつつ、ifで一部だけ取る」ようなことをしたくなることがあります。それでは実際にやってみましょう(バグ報告のPlunkerより引用)。

my-tag.tag
<my-tag>
  <div each={label, i in labels} if={i!=0} >{i} : {label}</div>
  <script>
    this.labels = ['a', 'b', 'c']
  </script>
</my-tag>

この<my-tag>をマウントすると、なんと「0:b、1:c」という表示になってしまって、配列のインデックスではなく表示される分だけのインデックスとなってしまいます。

回避策

とりあえず、「値が(バラバラなオブジェクトなど)全部違う」場合には、eachで取るインデックスの代わりに、Array.prototype.indexOfで配列から探すことで、応急措置にはなります(配列を走査するコストは発生しますが)。

外部リンク