LoginSignup
19
10

More than 5 years have passed since last update.

Vue で React の Fragment に相当するコンポーネントを使用する

Posted at

以下のような table を作りたい場合、React の Fragment に類する要素が必要となる。
https://reactjs.org/docs/fragments.html

<table>
  <tbody>
    <React.Fragment v-for="item in items">
      <tr>
        <td>{{item.name}}</td>
      </tr>
      <tr v-if="item.children">{{item.children.name}}</tr>
    </React.Fragment>
  </tbody>
</table>

なぜならば、table の仕様上、tbody 等(thead, tfooter) の直下には div などの要素はおいてはいけないからだ。(基本は tr がくるので) つまり以下のようにはできない。このようにした場合、table の挙動が保証されない。

<table>
  <tbody>
    <div v-for="item in items">
      <tr>
        <td>{{item.name}}</td>
      </tr>
      <tr v-if="item.children">{{item.children.name}}</tr>
    </div>
  </tbody>
</table>

vue には react の fragment に相当する要素がない

しかし Vue にはそれに相当する要素がない。(一時期あったバージョンもあるようだが)

解決策としては functional component 等が提案されているようだが、シンプルに fragment に類するコンポーネントを使いたい。

一応サードパーティ製のものがある

https://www.npmjs.com/package/vue-fragments
開発メンテが終了しているが、一応コンポーネントとしてある。
ただし、import 時の挙動がドキュメントとあっていなかったので、修正したものを個人的に公開した。本プロジェクトはメンテナンスをしていないようで、プルリクが通らないため。

使い方

npm i @superyusuke/vue-fragment
<template>
  <v-fragment>2</v-fragment>
</template>

<script>
import { VFragment } from '@superyusuke/vue-fragment'
export default {
  components: { VFragment }
}
</script>

注意

ただし、本家が Fragment を採用していない理由はなにかあるはずなので、このコンポーネントは何らかの問題を抱えている可能性がある。とくにパフォーマンスに関して、あまり高くないかもしれない。使わなくていい場合には使わない方がいいと思われる。

table を使うのをやめた

ただ、最終的には table を使用するのをやめようと今検討して動いている。table は高さの縦のラインが揃うことが利点だが、反面、スタイリングの自由度は低い。ほかのフロントエンドエンジニアに相談したところ、CSS Grid を使うのがよいのではないか、という結論に至った。IE 11 にも autoprefixer が対応させてくれる。

19
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
10