Vuetifyを使って綺麗な表を作る方法【v-data-table】
いつもご利用ありがとうございます。
この記事には広告が掲載されており、その広告費によって運営しています。
目次
Vuetify を使って綺麗な表(table)を作る方法についてまとめました。
v-data-table とは?
Vuetify には、簡単に、綺麗で機能性に優れた表を作ることが可能なコンポーネントが用意されています。
それがv-data-table
です。
機能性とは?
- ページネーション
- ソート(並び替え)
- フィルター
こういった機能を簡単につけることができます。
自作しようと思うと大変ですよね。
基本形
<script setup>
import { Head, Link } from "@inertiajs/vue3"
const headers = [
{
title: "タイトル",
value: "title",
},
{ title: "カテゴリー", value: "category" },
{ title: "内容", value: "content" },
]
const items = [
{
title: "タイトル1",
category: "カテゴリー1",
content: "内容ないよう内容ないよう内容ないよう内容ないよう内容ないよう1",
},
{
title: "タイトル2",
category: "カテゴリー2",
content: "内容ないよう内容ないよう内容ないよう内容ないよう内容ないよう2",
},
{
title: "タイトル1",
category: "カテゴリー1",
content: "内容ないよう内容ないよう内容ないよう内容ないよう内容ないよう2",
},
]
</script>
<template>
<div>
<head title="Welcome" />
<v-data-table
:headers="headers"
:items="items"
item-key="name"
items-per-page="5"
></v-data-table>
</div>
</template>
headers で表の見出しを作る
title
に表に表示したいテキスト、value
にプロパティを入れます。
const headers = [
{
title: "タイトル",
value: "title",
},
{ title: "カテゴリー", value: "category" },
{ title: "内容", value: "content" },
]
items で内容を表示する
headers の value で指定した、プロパティがその列に表示されます。
const items = [
{
title: "タイトル1",
category: "カテゴリー1",
content: "内容ないよう内容ないよう内容ないよう内容ないよう内容ないよう1",
},
{
title: "タイトル2",
category: "カテゴリー2",
content: "内容ないよう内容ないよう内容ないよう内容ないよう内容ないよう2",
},
{
title: "タイトル1",
category: "カテゴリー1",
content: "内容ないよう内容ないよう内容ないよう内容ないよう内容ないよう2",
},
]
コンポーネントに props を渡す
さきほどの headers や items を props で渡します。
<v-data-table
:headers="headers"
:items="items"
item-key="name"
items-per-page="5"
></v-data-table>
以上が基本形となります。
API などからデータを受け取った場合
変数にデータを格納し、props で渡せば表示できます。
<script setup>
import { Head } from "@inertiajs/vue3"
import { ref, onMounted } from "vue"
import axios from "axios"
const posts = ref([])
const headers = [
{ title: "タイトル", value: "title" },
{ title: "カテゴリー", value: "category" },
{ title: "内容", value: "content" },
]
const fetchPosts = async () => {
try {
const response = await axios.get("/api/posts") // APIエンドポイントを適宜変更
posts.value = response.data
} catch (error) {
console.error("Error fetching posts:", error)
}
}
onMounted(fetchPosts)
</script>
<template>
<div>
<head title="Welcome" />
<v-data-table
:headers="headers"
:items="posts"
item-key="id"
items-per-page="5"
></v-data-table>
</div>
</template>
items
が props 名でposts
が変数名です。
:items="posts"
1ページに表示するデータ量を変更する方法
items-per-page
で数字を指定します。
<v-data-table
:headers="headers"
:items="posts"
item-key="name"
items-per-page="100"
></v-data-table>
ソート(並び替え)を付ける方法
headers
にsortable
を付けると昇順、降順を選択する矢印が出ます。
const headers = [
{
title: "タイトル",
value: "title",
},
{ title: "カテゴリー", value: "category", sortable: true },
{ title: "内容", value: "content" },
]
初期の並び替えをしたい場合は、sort-by
に指定します。
const sortBy = [{ key: 'category', order: 'desc' }]
<v-data-table
:headers="headers"
:items="posts"
item-key="name"
items-per-page="5"
:sort-by="sortBy"
></v-data-table>
テキストで絞り込みしたい場合
search
という props に渡せば良いです。
入力欄を作って、v-model で関連する変数を指定。それをsearch
に渡します。
<script setup>
import { ref } from "vue"
const searchWord = ref("") //追記
//これまで書いてきたheadersなどは省略してます
</script>
<v-text-field v-model="searchWord" label="絞り込み"></v-text-field> //追記
<v-data-table
:headers="headers"
:items="posts"
item-key="name"
items-per-page="5"
:search="searchWord"
></v-data-table>
データ量が多すぎる場合
これまでのやり方は、データを一括で最初に取得し、それを表示するやり方でした。
大抵の場合、これで大丈夫でしょう。
ただ、このやり方だとデータ量が多くなると重くなってしまう可能性があり、それを改善する方法として
「サーバーサイドテーブル」と「仮想テーブル」が用意されています。
簡単なのは仮想テーブル
仮想テーブルはこれまでのやり方とほとんど変わらない方法で、行の一部分のみをレンダリングしてくれます。
なので、大きなデータを扱うことができます。
ただ、このやり方では、ページネーションを使うことができません。
v-data-table-virtual
コンポーネントに変えるだけで使えます。
<script setup>
import { ref, onMounted } from "vue"
defineProps({
posts: Array,
})
const headers = [
{
title: "タイトル",
value: "title",
},
{ title: "カテゴリー", value: "category", sortable: true },
{ title: "内容", value: "content" },
]
const searchWord = ref("")
</script>
<template>
<div>
<v-text-field v-model="searchWord" label="絞り込み"></v-text-field>
<v-data-table-virtual
:headers="headers"
:items="posts"
item-key="name"
:search="searchWord"
></v-data-table-virtual>
</div>
</template>
API を作り込まないといけないが、色々できるサーバーサイドテーブル
表の機能を触った際のイベントでサーバーと通信をして、新しいデータを取得しなおす形になります。
当然、サーバーが返すデータを作るのは我々なので、なかなか大変な作業となります。
ここでは大体の方針だけ紹介する形で許してください。
v-data-table-server
コンポーネントを使います。
<script setup>
import { ref, onMounted } from "vue"
defineProps({
posts: Array,
})
const headers = [
{
title: "タイトル",
value: "title",
},
{ title: "カテゴリー", value: "category", sortable: true },
{ title: "内容", value: "content" },
]
const loadItems = ({ page, itemsPerPage, sortBy }) => {
console.log(page)
console.log(itemsPerPage)
console.log(sortBy)
}
</script>
<template>
<div>
<v-data-table-server
:items="posts"
:headers="headers"
@update:options="loadItems"
></v-data-table-server>
</div>
</template>
表の操作が行われた時、ページ数やソートされた情報が伝わり、それを元にサーバーと Fetch します。
イメージとしてはこんな感じで、その情報に応じてサーバーからデータを返します。
const posts = ref([])
const loadItems = ({ page, itemsPerPage, sortBy }) => {
console.log(page)
console.log(itemsPerPage)
const { data } = await axios.get('https://localhost/api/posts',{
params: {
page: page,
per_page: itemsPerPage,
}
})
posts.value = data
}
以上、v-data-table
についてやってみました。
さくっと表を作りたい時に便利だと思います。
誰かの参考になれば幸いです。