🐈
VuetifyのDataTableをいじってみる
基本形
- headersにテーブルヘッダー情報
- itemsにテーブルデータ情報
Table.vue
<template>
<div>
<v-data-table
:headers="headers"
:items="items"
:items-per-page="5"
class="elevation-1"
/>
</div>
</template>
<script>
import { defineComponent } from "@vue/composition-api"
export default defineComponent({
setup() {
const headers = [
{
text: "Dessert (100g serving)",
align: "start",
sortable: false,
value: "name",
},
{ text: "Calories", value: "calories" },
{ text: "Fat (g)", value: "fat" },
]
const items = [
{
name: "Frozen Yogurt",
calories: 159,
fat: 6.0,
},
{
name: "Ice cream sandwich",
calories: 237,
fat: 9.0,
},
{
name: "Eclair",
calories: 262,
fat: 16.0,
},
]
return { headers, items }
},
})
</script>
再利用可能なテーブルにする(基本)
propsでheadersとitemsを受け取れるようにする
Table.vue
<template>
<div>
<v-data-table
:headers="headers"
:items="items"
:items-per-page="5"
class="elevation-1"
/>
</div>
</template>
<script>
import { defineComponent } from "@vue/composition-api"
export default defineComponent({
props: {
headers: Array,
items: Array,
},
setup() {
return {}
},
})
</script>
Home.vue
<template>
<div>
<Table :headers="headers" :items="items" />
</div>
</template>
<script>
import { defineComponent } from "@vue/composition-api"
import Table from "@/components/Table"
import VslotTemplate from "@/components/VslotTemplate"
export default defineComponent({
components: {
Table,
VslotTemplate,
},
setup() {
const headers = [
{
text: "Dessert (100g serving)",
align: "start",
sortable: false,
value: "name",
},
{ text: "Calories", value: "calories" },
{ text: "Fat (g)", value: "fat" },
]
const items = [
{
name: "Frozen Yogurt",
calories: 159,
fat: 6.0,
},
{
name: "Ice cream sandwich",
calories: 237,
fat: 9.0,
},
{
name: "Eclair",
calories: 262,
fat: 16.0,
},
]
return { headers, items }
},
})
</script>
再利用可能なテーブルにする(slot編)
例えばテーブルの、1番目のカラムにアイコンを表示したい場合。
v-slot:item.<columName>を使って、アイコンを挿入する(上書き)
Table.vue
<template>
<div>
<v-data-table
:headers="headers"
:items="items"
:items-per-page="5"
class="elevation-1"
>
<template v-slot:item.actions>
<v-btn icon><v-icon>mdi-pencil</v-icon></v-btn>
<v-btn icon><v-icon>mdi-menu</v-icon></v-btn>
</template>
</v-data-table>
</div>
</template>
<script>
import { defineComponent } from "@vue/composition-api"
export default defineComponent({
props: {
headers: Array,
items: Array,
},
setup() {
return {}
},
})
</script>
headersに空カラムを追加 + itemsの各itemに空文字を設定する
Home.vue
<template>
<div>
<Table :headers="headers" :items="items" />
</div>
</template>
<script>
import { defineComponent } from "@vue/composition-api"
import Table from "@/components/Table"
import VslotTemplate from "@/components/VslotTemplate"
export default defineComponent({
components: {
Table,
VslotTemplate,
},
setup() {
const headers = [
{ text: "", value: "actions" }, //追加
{
text: "Dessert (100g serving)",
align: "start",
sortable: false,
value: "name",
},
{ text: "Calories", value: "calories" },
{ text: "Fat (g)", value: "fat" },
]
const items = [
{
actions: "", //追加
name: "Frozen Yogurt",
calories: 159,
fat: 6.0,
},
{
actions: "", //追加
name: "Ice cream sandwich",
calories: 237,
fat: 9.0,
},
{
actions: "", //追加
name: "Eclair",
calories: 262,
fat: 16.0,
},
]
return { headers, items }
},
})
</script>
ただし、、、
これだと、固定アイコンが入ってしまうので、再利用性が低い。
なので、このように変更する。
Table.vue
<template>
<div>
<v-data-table
:headers="headers"
:items="items"
:items-per-page="5"
class="elevation-1"
>
<template v-slot:item.actions>
<slot name="actions"> </slot>
</template>
</v-data-table>
</div>
</template>
<script>
import { defineComponent } from "@vue/composition-api"
export default defineComponent({
props: {
headers: Array,
items: Array,
},
setup() {
return {}
},
})
</script>
Table.vueファイルで作った独自スロット(name="actions")にアイコンを書く
Home.vue
<template>
<div>
<Table :headers="headers" :items="items">
<template #actions>
<v-btn icon><v-icon>mdi-pencil</v-icon></v-btn>
<v-btn icon><v-icon>mdi-menu</v-icon></v-btn>
</template>
</Table>
</div>
</template>
<script>
//scriptは上と同じなので省略、
</script>
さらに再利用度を高めていく
編集ボタンを押したときに、itemのIDを取得する動きを実現したい。
(編集ページにitemのIDを渡すことが多いため)
vue slotの基礎
まず、itemsを参照できるようにするため、v-slotテンプレートに="items"を追記する
<template v-slot:item.actions>
↓
<template v-slot:item.actions="items">
さらに、独自スロットにIDを渡せるようにする。
これをすることで、Home.vueでidを参照することが出来るようになる。
<slot name="actions" :id="items.item.id" />
Table.vue
<template>
<div>
<v-data-table
:headers="headers"
:items="items"
:items-per-page="5"
class="elevation-1"
>
<template v-slot:item.actions="items">
<slot name="actions" :id="items.item.id" />
</template>
</v-data-table>
</div>
</template>
ちなみに、v-slot:item.actions="items"のitemsの中身は
こういうデータ構造になっている。
{
"item": {
"actions": "",
"id": "1",
"name": "Frozen Yogurt",
"calories": 159,
"fat": 6,
"carbs": 24,
"protein": 4,
"iron": "1%"
},
"isMobile": false,
"header": {
"text": "",
"value": "actions"
},
"index": 0,
"value": ""
}
なので、分割代入を使って、こう書くことも可能。
Table.vue
<template v-slot:item.actions="{item}">
<slot name="actions" :id="item.id" />
</template>
Home.vueでは、このようにして、Table.vueのslotで設定したプロパティ(id="item.id")にアクセスできるようにする。
<template #actions="slotProps">
ちなみに、このslotPropsはお好みの名前に変更しても問題ない。
Home.vue
<template>
<Table :headers="headers" :items="items">
<template #actions="slotProps">
<v-btn icon @click="openEditPage(slotProps.id)">
<v-icon>mdi-pencil</v-icon>
</v-btn>
<v-btn icon><v-icon>mdi-menu</v-icon></v-btn>
</template>
</Table>
</template>
これも分割代入を使うことで、短く書ける。
Home.vue
<template>
<Table :headers="headers" :items="items">
<template #actions="{id}">
<v-btn icon @click="openEditPage(id)">
<v-icon>mdi-pencil</v-icon>
</v-btn>
<v-btn icon><v-icon>mdi-menu</v-icon></v-btn>
</template>
</Table>
</template>
Discussion