Vuetifyでレスポンシブのテーブルを作る - inokawablog

Vuetifyでレスポンシブのテーブルを作る

Vuetifyを使ってデータを表示するレスポンシブのテーブルを作成します。

vuetifyを使えば、簡単にすばやくサイトを作成できます。最近はテーマなども充実してきて、特に凝ったデザインでない限りはvuetifyを使った方がいいという感じです。

最近だとVuetifyのストアでグッズとかも結構出てるんですけど、あんまりおしゃれなものがないのでもう少ししっかり作ってくれたらなって感じはします(笑)。

 

vuetifyのテーブルにはSimple tableData tableがあるのですが、今回はData tableを作っていきます。

Vuetifyの公式ドキュメントではテーブルの作成までは書いてあるのですが、レスポンシブ対応までは書いてありません。

公式ドキュメント

 

Vuetifyでレスポンシブのテーブルを作る

気軽に使いたい方はCDNで使ってみてください。

<link href="https://cdn.jsdelivr.net/npm/@mdi/font@3.x/css/materialdesignicons.min.css" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">

 

template

<v-data-table
  :headers="headers"
  :items="desserts"
  class="elevation-1"
>
  <template v-slot:item="{ item }">
    <tr @click="console.log(item)">
      <td class="text-left" v-for="header in headers" :class="{'v-data-table__mobile-row': screenWidthOver(windowWidth)}">
        <div class="v-data-table__mobile-row__wrapper" v-if="screenWidthOver(windowWidth)">
          <div class="v-data-table__mobile-row__header">{{ header.text }}</div>
          <div class="text-right">{{ item[header.value] }}</div>
        </div>
        <div v-else>
          {{ item[header.value] }}
        </div>
      </td>
    </tr>
  </template>
</v-data-table>

data tableのslotを使いテーブルのコンテンツの内容を書き換えています。そして、classを画面幅によって動的に設定し、表示を変えています。

 

script

<script>
  export default {
    data: () => ({
      windowWidth: 0,
      mobileScreenWidth: 600,
      headers: [
        {text: 'Dessert (100g serving)',align: 'left',sortable: false,value: 'name',},
        { text: 'Calories', value: 'calories' },
        { text: 'Fat (g)', value: 'fat' },
        { text: 'Carbs (g)', value: 'carbs' },
        { text: 'Protein (g)', value: 'protein' },
        { text: 'Iron (%)', value: 'iron' },
      ],
      desserts: [
        {name: 'Frozen Yogurt',calories: 159,fat: 6.0,carbs: 24,protein: 4.0,iron: '1%',},
        {name: 'Ice cream sandwich',calories: 237,fat: 9.0,carbs: 37,protein: 4.3,iron: '1%',},
        {name: 'Eclair',calories: 262,fat: 16.0,carbs: 23,protein: 6.0,iron: '7%',},
        {name: 'Cupcake',calories: 305,fat: 3.7,carbs: 67,protein: 4.3,iron: '8%',},
        {name: 'Gingerbread',calories: 356,fat: 16.0,carbs: 49,protein: 3.9,iron: '16%',},
        {name: 'Jelly bean',calories: 375,fat: 0.0,carbs: 94,protein: 0.0,iron: '0%',},
        {name: 'Lollipop',calories: 392,fat: 0.2,carbs: 98,protein: 0,iron: '2%',},
        {name: 'Honeycomb',calories: 408,fat: 3.2,carbs: 87,protein: 6.5,iron: '45%',},
        {name: 'Donut',calories: 452,fat: 25.0,carbs: 51,protein: 4.9,iron: '22%',},
        {name: 'KitKat',calories: 518,fat: 26.0,carbs: 65,protein: 7,iron: '6%',},
      ],
    }),
    watch: {
      windowWidth(newWidth, oldWidth) {
        this.screenWidthOver(newWidth)
      }
    },
    mounted() {
      this.windowWidth = window.innerWidth
      window.onresize = () => {
          this.windowWidth = window.innerWidth
      }
    },
    methods: {
      screenWidthOver: function (screenWidth) {
        if (screenWidth < this.mobileScreenWidth) {
          return true
        }else{
          return false
        }
      },
    }
  }
</script>

 

windowWidth

画面幅です。mountedのタイミングで最初の画面幅を入れ、window.onresizeで、resizeされるたびにwindowWidthにwindow.innerWidthが代入されます。

それをwatchで監視して、変更があった場合に、screenWidthOverの処理が走ります。

screenWidthOver

受け取った画面幅screenWidthがmobileScreenWidth 600によって条件分岐させています。ここで画面幅によって細かく設定することもできます。

 

これで以上です。

ちなみに、v-data-table__mobile-row は、難しいことはやっておらず、display:blockをやっているだけです。


 

Vuetifyは日本語の記事が少ないので、しっかりと残していきたいと思います。