29
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VueAdvent Calendar 2022

Day 18

Vuetify3 でよく使うコンポーネントのメモ(2)

Last updated at Posted at 2022-08-25

このページは下記リンク先へ移行中です。

以下の記事は内容が古い可能性があります。新しい情報については上記記事を参照してください。

内容

このページには、Vuetify3 の下記のコンポーネントについての覚書きがあります。

関連記事

リストとテーブル

リスト (v-list / v-list-item)

複数の項目を行で並べて表示します。HTML の ul/li 要素の見た目を綺麗にした感じです。

image.png

コード:

App.vue
<template>
  <v-container>
    <v-list>
      <v-list-item>
        <v-list-item-tile>HOGE1</v-list-item-tile>
      </v-list-item>
      <v-list-item>
        <v-list-item-tile>HOGE2</v-list-item-tile>
      </v-list-item>
      <v-list-item>
        <v-list-item-tile>HOGE3</v-list-item-tile>
      </v-list-item>
    </v-list>
  </v-container>
</template>

InnerText と v-lite-item-title の違い

リファレンスのページを見ると、v-list-item-title を使うように書かれているのですが、使わなくても表示が変わらない気がします。ただ、いずれ変更があるかもしれないので、v-list-item-title を使っておいたほうがよさそうです。

image.png

コード:

App.vue
<template>
  <div class="d-flex">
  <v-container>
    <v-list>
      <v-list-item>HOGE1</v-list-item>
      <v-list-item>HOGE2</v-list-item>
      <v-list-item>HOGE3</v-list-item>
    </v-list>
    InnerText
  </v-container>

  <v-container>
    <v-list>
      <v-list-item>
        <v-list-item-title>HOGE1</v-list-item-title>
      </v-list-item>
      <v-list-item>
        <v-list-item-title>HOGE2</v-list-item-title>
      </v-list-item>
      <v-list-item>
        <v-list-item-title>HOGE3</v-list-item-title>
      </v-list-item>
    </v-list>
    v-list-item-title
  </v-container>

  <v-container>
    <v-list>
      <v-list-item>HOGE1
        <v-list-item-subtitle>foobar</v-list-item-subtitle>
      </v-list-item>
      <v-list-item>HOGE2
        <v-list-item-subtitle>foobar</v-list-item-subtitle>
      </v-list-item>
      <v-list-item>HOGE3
        <v-list-item-subtitle>foobar</v-list-item-subtitle>
      </v-list-item>
    </v-list>
    InnerText + v-list-item-subtitle
  </v-container>

  <v-container>
    <v-list>
      <v-list-item>
        <v-list-item-title>HOGE1</v-list-item-title>
        <v-list-item-subtitle>foobar</v-list-item-subtitle>
      </v-list-item>
      <v-list-item>
        <v-list-item-title>HOGE2</v-list-item-title>
        <v-list-item-subtitle>foobar</v-list-item-subtitle>
      </v-list-item>
      <v-list-item>
        <v-list-item-title>HOGE3</v-list-item-title>
        <v-list-item-subtitle>foobar</v-list-item-subtitle>
      </v-list-item>
    </v-list>
    v-lite-item-title + v-list-item-subtitle
  </v-container>

  </div>
</template>

クリックされた項目の値を取得する

value 属性を付けると、クリックできるようになります。クリックした v-lite-itemvalue の値は、v-list@change:select で取得できます。

list1.gif

コード:

App.vue
<template>
  <v-container>
    <v-list @click:select="clickItem">
      <v-list-item value="1">
        <v-list-item-title>HOGE1</v-list-item-title>
      </v-list-item>
      <v-list-item value="2">
        <v-list-item-title>HOGE2</v-list-item-title>
      </v-list-item>
      <v-list-item value="3">
        <v-list-item-title>HOGE3</v-list-item-title>
      </v-list-item>
    </v-list>
    <h1>{{ message }}</h1>
  </v-container>
</template>
<script>
export default {
  data: () => ({
    message: ""
  }),
  methods: {
    clickItem(arg)
    {
      this.message = arg.id;
    }
  }
}
</script>

配列による生成

v-listitems 属性を使って、配列から生成するほうが楽です。生成する元となる配列を :items で指定します。item-titlev-list-item-title を生成するためのプロパティを、item-subtitlev-list-item-subtitle を生成するためのプロパティをそれぞれ指定します。item-valuev-list-item をクリックしたときに取得できる値を生成するためのプロパティを指定します。

動作自体は、上の例と全く同じになります。

list1.gif

コード:

App.vue
<template>
  <v-container>
    <v-list 
      @click:select="clickItem"
      :items="listItems"
      item-title="name"
      item-value="id"
    >
    </v-list>
    <h1>{{ message }}</h1>
  </v-container>
</template>
<script>
export default {
  data: () => ({
    listItems: [
        {
          name: "Hoge1",
          id: 1
        },
        {
          name: "Hoge2",
          id: 2
        },
        {
          name: "Hoge3",
          id: 3
        },
    ],
    message: ""
  }),
  methods: {
    clickItem(arg)
    {
      this.message = arg.id;
    }
  }
}
</script>

v-list はオプションが豊富で、いろんなことができます。

list2.gif

リストの途中にサブタイトルをつけたり、アイコンを付けたり、仕切り線を付けたり、クリックしたときの色をかえたりできます。

App.vue
<template>
  <v-container>
    <v-list
      @click:select="clickItem"
      :items="listItems"
      item-title="name"
      item-value="id"
    >
    </v-list>
    <h1>{{ message }}</h1>
  </v-container>
</template>
<script>
export default {
  data: () => ({
    listItems: [
        { type: 'subheader', name: 'Group #1' },
        {
          name: "Hoge1",
          id: 1,
          props: {
            prependIcon: 'mdi-home',
            color: "red"
          },
        },
        {
          props: {
            prependIcon: 'mdi-file',
          },
          name: "Hoge2",
          id: 2
        },
        { type: 'divider', inset: true },
        { type: 'subheader', name: 'Group #2' },
        {
          props: {
            appendIcon: 'mdi-home',
          },
          name: "Hoge3",
          id: 3
        },
        {
          icon: "mdi-home",
          name: "Hoge4",
          id: 4
        },
    ],
    message: ""
  }),
  methods: {
    clickItem(arg)
    {
      this.message = arg.id;
    }
  }
}
</script>

入れ子になったリスト(サブリスト)を作ることもできます。詳しくは、公式のドキュメントを見てください。

なお、リストは単体で使われることもありますが、他のコンポーネントの一部として使われることも多いです。代表的なものは、下記です。

  • v-navigation-drawer
  • v-menu

v-menu については下記の「メニュー」の項目を見てください。

v-navigation-drawer については、nav 属性を付けてフォントが少し小さいリストを使うことが多いです。

list4.gif

コード:

App.vue
<template>
  <v-container>
    <v-layout>
      <v-btn @click="drawer = !drawer">
        Navigator
      </v-btn>

      <v-navigation-drawer v-model="drawer">
        <v-list 
          nav
          density="compact"
          :items="listItems"
          item-title="name"
          item-value="id"
        >
        </v-list>
      </v-navigation-drawer>
    </v-layout>
  </v-container>
</template>
<script>
export default {
  data: () => ({
    drawer: false,
    listItems: [
      { type: 'header', name: 'Main Menu' },
      { type: 'divider', inset: true },
      {
        name: "Home",
        id: 1,
        props: {
          prependIcon: 'mdi-home',
        },
      },
      {
        name: "File",
        id: 2,
        props: {
          prependIcon: 'mdi-file',
        },
      },
    ]
  }),
}
</script>

max-height を指定すると、指定された高さからリストの項目があふれると、自動的にスクロールバーがつきます。

list5.gif

コード:

App.vue
<template>
  <v-container>
      <v-list
        :items="listItems"
        item-title="name"
        item-value="id"
        max-height="200"
      >
      </v-list>
  </v-container>
</template>
<script>
export default {
  data: () => ({
    listItems: [
      { name: "Home1", id: 1,},
      { name: "Home2", id: 2,},
      { name: "Home3", id: 3,},
      { name: "Home4", id: 4,},
      { name: "Home5", id: 5,},
      { name: "Home6", id: 6,},
      { name: "Home7", id: 7,},
      { name: "Home8", id: 8,},
      { name: "Home9", id: 9,},
      { name: "Home10", id: 10,},
    ]
  }),
}
</script>

v-list は、どういうわけか v-sheet の中に置くと、v-sheet のサイズを超えて下側へはみ出してしまうことがあります。リストのサイズを制限したい場合は、v-sheet ではなく v-card の中に入れるようにします。

image.png

上の図のように、カードとシートでほぼ同等の設定にしても、ソート側は v-list のサイズがシートを超えると、外へはみ出します。

App.vue
<template>
  <v-container class="d-flex">
    <v-card height="200" width="300" color="black" class="pa-3 ma-2">
      <v-card-title>CARD</v-card-title>
      <v-list
        :items="listItems"
        item-title="name"
        item-value="id"
      >
      </v-list>
    </v-card>
    <v-sheet height="200" width="300" class="pa-3 ma-2 bg-black">
      <h3 class="my-3">ShEET</h3>
      <v-list
        :items="listItems"
        item-title="name"
        item-value="id"
      >
      </v-list>
    </v-sheet>
  </v-container>
</template>
<script>
export default {
  data: () => ({
    listItems: [
      { name: "Home1", id: 1,},
      { name: "Home2", id: 2,},
      { name: "Home3", id: 3,},
      { name: "Home4", id: 4,},
      { name: "Home5", id: 5,},
      { name: "Home6", id: 6,},
      { name: "Home7", id: 7,},
      { name: "Home8", id: 8,},
      { name: "Home9", id: 9,},
      { name: "Home10", id: 10,},
    ]
  }),
}
</script>

テーブル v-table

表を作ります。いくつかの値が組になっているデータの表示に便利です。

image.png

コード:

App.vue
<template>
  <v-container>
    <v-table>
      <thead>
        <tr>
          <th class="text-left">
            都道府県
          </th>
          <th class="text-right">
            No
          </th>
          <th class="text-right">
            面積
          </th>
        </tr>
      </thead>
      <tbody>
        <tr
          v-for="item in todohuken"
          :key="item.name"
        >
          <td>{{ item.name }}</td>
          <td class="text-right">{{ item.no }}</td>
          <td class="text-right">{{ item.area }}</td>
        </tr>
      </tbody>
    </v-table>
  </v-container>
</template>
<script>
export default {
  data () {
    return {
      todohuken: [
        {name: '北海道', no: 1,  area: 83456.20 },
        {name: '長野県', no: 2,  area: 13562.23 },
        {name: '東京都', no: 3,  area: 2187.42 },
        {name: '和歌山県', no: 4,area: 4726.12 },
        {name: '香川県', no: 5,  area: 1876.47 },
        {name: '神奈川県', no: 6,area: 2415.84 },
        {name: '岡山県', no: 7,  area: 7113.00 },
        {name: '鹿児島県', no: 8,area: 9187.80 },
        {name: '宮城県', no: 9,  area: 7285.73 },
        {name: '石川県', no: 10, area: 4185.47 },                                
      ],
    }
  },
}
</script>

height を指定すると、その高さを超えたときにスクロールバーが表示されすようになります。リストと違って、max-height ではうまくいきません。

density="compact" を指定すると、行の縦幅が少し詰まります。

image.png

App.vue
<template>
  <v-container>
    <v-table 
      height="300"
      density="compact"
    >
      <thead>
        <tr>
          <th class="text-left">
            都道府県
          </th>
          <th class="text-right">
            No
          </th>
          <th class="text-right">
            面積
          </th>
        </tr>
      </thead>
      <tbody>
        <tr
          v-for="item in todohuken"
          :key="item.name"
        >
          <td>{{ item.name }}</td>
          <td class="text-right">{{ item.no }}</td>
          <td class="text-right">{{ item.area }}</td>
        </tr>
      </tbody>
    </v-table>
  </v-container>
</template>
<script>
export default {
  data () {
    return {
      todohuken: [
        {name: '北海道', no: 1,  area: 83456.20 },
        {name: '長野県', no: 2,  area: 13562.23 },
        {name: '東京都', no: 3,  area: 2187.42 },
        {name: '和歌山県', no: 4,area: 4726.12 },
        {name: '香川県', no: 5,  area: 1876.47 },
        {name: '神奈川県', no: 6,area: 2415.84 },
        {name: '岡山県', no: 7,  area: 7113.00 },
        {name: '鹿児島県', no: 8,area: 9187.80 },
        {name: '宮城県', no: 9,  area: 7285.73 },
        {name: '石川県', no: 10, area: 4185.47 },                                
      ],
    }
  },
}
</script>

データテーブル v-data-table

v-table よりリッチな感じでデータの表示ができます。pagenation の機能がデフォルトで付いているため、データの個数を区切って少しずつ表示させことが簡単にできるのが非常に便利です。またソート機能もデフォルトでついています。フィルタ機能(検索機能)もあります。

データの表示欄についても、チェックボックをつけたり、アイコンを表示したり、いろいろできます。

なお vuetify 3.3.6 では Vuetify Labs として実装されています。実験段階の実装ということで、動作については保証されていません。

image.png

App.vue
<template>
  <v-container>
    <v-data-table
      v-model:items-per-page="itemsPerPage"
      :headers="headers"
      :items="dataset"
      item-value="name"
      class="elevation-1"
    ></v-data-table>
  </v-container>
</template>

<script>
import { VDataTable } from 'vuetify/lib/labs/components.mjs';

export default {
  data: () => ({
    itemsPerPage: 5,

    headers: [
      {
        title: '都道府県',
        align: 'start',
        sortable: false,
        key: 'name',
      },
      { title: 'no', align: 'end', key: 'no' },
      { title: '面積', align: 'end', key: 'area' },
    ],
    dataset: [
      {name: '北海道', no: 1,  area: 83456.20 },
      {name: '長野県', no: 2,  area: 13562.23 },
      {name: '東京都', no: 3,  area: 2187.42 },
      {name: '和歌山県', no: 4,area: 4726.12 },
      {name: '香川県', no: 5,  area: 1876.47 },
      {name: '神奈川県', no: 6,area: 2415.84 },
      {name: '岡山県', no: 7,  area: 7113.00 },
      {name: '鹿児島県', no: 8,area: 9187.80 },
      {name: '宮城県', no: 9,  area: 7285.73 },
      {name: '石川県', no: 10, area: 4185.47 },                                
    ],
  }),
  components: {
    VDataTable,
  }
}
</script>

Labs の実験的な機能なので、VDataTable コンポーネントの明示的な読み込みと追加が必要です(バージョン 3.3.6 現在)。

v-data-table についてはボリュームが非常に大きいので、別の記事にしました。

複数の画面を切り替える

複数の画面をスライドショーのように切り替える v-carousels

いわゆるカルーセルというやつです。

carousel1.gif

コード:

App.vue
<template>
<v-container>
  <v-carousel v-model="model">
    <v-carousel-item>
      <v-sheet
        class="bg-red"
        height="400"
        tile
      >
        <h1 class="text-white">Window 1</h1>
      </v-sheet>
    </v-carousel-item>
    <v-carousel-item>
      <v-sheet
        class="bg-blue"
        height="400"
        tile
      >
        <h1 class="text-white">Window 2</h1>
      </v-sheet>
    </v-carousel-item>
    <v-carousel-item>
      <v-sheet
        class="bg-green"
        height="400"
        tile
      >
        <h1 class="text-white">Window 3</h1>
      </v-sheet>
    </v-carousel-item>
  </v-carousel>
  <h1>{{model}}</h1>
</v-container>  
</template>
<script>
export default {
  data: () => ({
    model: 0,
  })
}
</script>

v-for で作成するほうが楽です。

App.vue
<template>
<v-container>
  <v-carousel v-model="model">
    <v-carousel-item v-for="item in items" :key="item.color">
      <v-sheet
        :color="item.color"
        height="100%"
        tile
      >
        <h1 class="text-white">Window {{item.num}}</h1>
      </v-sheet>
    </v-carousel-item>
  </v-carousel>
  <h1>{{model}}</h1>
</v-container>  
</template>
<script>
export default {
  data: () => ({
    model: 0,
    items: [
      {
        color: "red",
        num: 1
      },
      {
        color: "blue",
        num: 2
      },
      {
        color: "green",
        num: 3
      },
    ]
  })
}
</script>

v-carousel-item の中に自作のコンポーネントを入れると、疑似的なページの切り替えができます。

carousel1.gif

動作自体は全く同じです。

コード:

App.vue
<template>
<v-container>
  <v-carousel v-model="model">
    <v-carousel-item><HogePageA/></v-carousel-item>
    <v-carousel-item><HogePageB/></v-carousel-item>
    <v-carousel-item><HogePageC/></v-carousel-item>
  </v-carousel>
  <h1>{{model}}</h1>
</v-container>  
</template>
<script>
import HogePageA from './components/HogePageA.vue';
import HogePageB from './components/HogePageB.vue';
import HogePageC from './components/HogePageC.vue';

export default {
  data: () => ({
    model: 0
  }),
  components: {
    HogePageA, 
    HogePageB,
    HogePageC
  }
}
</script>

HogePageA.vue

./components/HogePageA.vue
<template>
    <v-sheet class="bg-red" height="400" tile>
        <h1 class="text-white">Window 1</h1>
    </v-sheet>
</template>

HogePageB.vue

./components/HogePageB.vue
<template>
    <v-sheet class="bg-blue" height="400" tile>
        <h1 class="text-white">Window 2</h1>
    </v-sheet>
</template>

HogePageC.vue

./components/HogePageC.vue
<template>
    <v-sheet class="bg-green" height="400" tile>
        <h1 class="text-white">Window 3</h1>
    </v-sheet>
</template>

v-model の値をプログラム内で変更すれば、強制的に特定のページを表示させることもできます。

詳しくは公式ドキュメントを参照してください。

複数の画面をタブで切り替える v-tabs

タブを使って画面を切り替えます。

tabs1.gif

App.vue
<template>
<v-app>
  <v-container class="pa-2">
    <v-tabs
      v-model="tab"
    >
      <v-tab value="1">Item One</v-tab>
      <v-tab value="2">Item Two</v-tab>
      <v-tab value="3">Item Three</v-tab>
    </v-tabs>

    <v-window v-model="tab">
      <v-window-item value="1">
        <v-sheet
          color="red"
          height="400"
          tile
        >
          <h1 class="text-white">Window 1</h1>
        </v-sheet>
      </v-window-item>

      <v-window-item value="2">
        <v-sheet
          color="blue"
          height="400"
          tile
        >
          <h1 class="text-white">Window 2</h1>
        </v-sheet>
      </v-window-item>

      <v-window-item value="3">
        <v-sheet
          color="green"
          height="400"
          tile
        >
          <h1 class="text-white">Window 3</h1>
        </v-sheet>
      </v-window-item>
    </v-window>
  </v-container>
</v-app>
</template>
<script>
export default {
  data: () => ({
    tab: null,
  }),
}
</script>

タブ自体は v-tabs で表示します。切り替える画面は v-window で作ります。双方のv-model に同じ変数を割り当てて置くと、v-tabs の切り替えに連動して `v-window 側が切り替わります。

カルーセルと同様に、切り替える画面をコンポーネントとして与えると、疑似的にページ切り替えができます。

tabs1.gif

動作自体は同じです。

コード:

App.vue
<template>
  <v-container class="pa-2">
    <v-tabs
      v-model="tab"
    >
      <v-tab value="1">Item One</v-tab>
      <v-tab value="2">Item Two</v-tab>
      <v-tab value="3">Item Three</v-tab>
    </v-tabs>

    <v-window v-model="tab">
      <v-window-item value="1"><HogePageA/></v-window-item>
      <v-window-item value="2"><HogePageB/></v-window-item>
      <v-window-item value="3"><HogePageC/></v-window-item>
    </v-window>
  </v-container>
</template>
<script>
import HogePageA from './components/HogePageA.vue';
import HogePageB from './components/HogePageB.vue';
import HogePageC from './components/HogePageC.vue';

export default {
  data: () => ({
    tab: 0
  }),
  components: {
    HogePageA,
    HogePageB,
    HogePageC,
  }
}
</script>

HogePageA.vue

./components/HogePageA.vue
<template>
    <v-sheet class="bg-red" height="400" tile>
        <h1 class="text-white">Window 1</h1>
    </v-sheet>
</template>

HogePageB.vue

./components/HogePageB.vue
<template>
    <v-sheet class="bg-blue" height="400" tile>
        <h1 class="text-white">Window 2</h1>
    </v-sheet>
</template>

HogePageC.vue

./components/HogePageC.vue
<template>
    <v-sheet class="bg-green" height="400" tile>
        <h1 class="text-white">Window 3</h1>
    </v-sheet>
</template>

タブ自体は、単純に値を選ぶことのできるコンポーネントなので、画面の切り替え以外の目的にも使えます。ただ、この用途につかうのであれば、v-btn-toggle を使うほうが良いです。

tabs2.gif

コード:

App.vue
<template>
  <v-container class="pa-2">
    <v-tabs
      v-model="tab"
    >
      <v-tab value="1">Item One</v-tab>
      <v-tab value="2">Item Two</v-tab>
      <v-tab value="3">Item Three</v-tab>
    </v-tabs>
    <h1>{{tab}}</h1>
  </v-container>
</template>
<script>
export default {
  data: () => ({
    tab: 0
  }),
}
</script>

タブに色つけるには、v-app-bar, v-sytem-bar, v-toolbar, v-card などのスタイルが指定できるコンポーネントに入れる必要があります。v-tabscolor は、選択されたタブの色として使われます。

image.png

コード:

App.vue
<template>
  <v-container class="pa-2">
    <v-toolbar color="primary">
      <v-tabs
        v-model="tab"
        color="secondary"
      >
        <v-tab :value="n" v-for="n in 5">Tab {{n}}</v-tab>
      </v-tabs>
    </v-toolbar>
    <h1>{{tab}}</h1>
  </v-container>
</template>
<script>
export default {
  data: () => ({
    tab: 0
  }),
}
</script>

縦方向のタブも作れます。

image.png

コード:

App.vue
<template>
  <v-container class="pa-2 d-flex">
    
    <v-tabs
      v-model="tab"
      direction="vertical"
      color="primary"
    >
      <v-tab :value="n" v-for="n in 5">Tab {{n}}</v-tab>
    </v-tabs>
    
    <h1>{{tab}}</h1>
    
  </v-container>
</template>
<script>
export default {
  data: () => ({
    tab: 0
  }),
}
</script>

v-app-barv-toolbar にいれるときに <template v-slot:extension> を使うと、デフォルトのバーの下にタブの行を分けて表示できます。

image.png

コード:

App.vue
<template>
  <v-app>
    <v-app-bar color="primary">
       <v-app-bar-nav-icon></v-app-bar-nav-icon>

      <v-app-bar-title>
        Application
      </v-app-bar-title>

      <v-btn icon="mdi-home">
      </v-btn>
    
      <template v-slot:extension>
        <v-spacer></v-spacer>
        <v-tabs
          v-model="tab"
        >
          <v-tab :value="n" v-for="n in 5" :key="n">Tab {{n}}</v-tab>
        </v-tabs>
        <v-spacer></v-spacer>
      </template>

    </v-app-bar>    
    <v-main>
      <v-container>
        <h1>{{tab}}</h1>
      </v-container>
    </v-main>
  </v-app>
</template>
<script>
export default {
  data: () => ({
    tab: 0
  }),
}
</script>

詳細は公式ページを見てください。

大量のデータを一定の個数ごとにページに分けて表示する v-pagination

Google の検索とかで、検索結果が大量にあるときに、表示しきれない部分を次のページ以降に送って、ページ切り替えをして読めるようにするいみたいなコンポーネントです。

v-pagination 自体はただのボタンで、ページを送る機能はありません。どのページを表示するかは、選択されたページ番号から自分で作成する必要があります。

最初のページの番号は 1 です。0 を指定すると、どのページ番号も選択されていない状態になります。length を超えるページ番号を指定しても、どのページ番号も選択されていない状態になります。

page1.gif

コード:

App.vue
<template>
  <v-container>
    <v-container>
      <v-row>
        <v-col cols="3" v-for="n in 8" :key="n">
          <v-card height="200">
            <v-card-title>Card{{n + 6*(page-1)}}</v-card-title>
          </v-card>
        </v-col>
      </v-row>
    </v-container>
    <v-pagination
      v-model="page"
      length="6"
    ></v-pagination>
  </v-container>
</template>
<script>
export default {
  data () {
    return {
      page: 1,
    }
  },
}
</script>

ページ数が多すぎるときに、total-visible を指定しておくと、ページ番号を表示する上限を指定できます。

image.png

コード:

App.vue
<template>
  <v-container>
    <v-container>
      <v-row>
        <v-col cols="3" v-for="n in 8" :key="n">
          <v-card height="200">
            <v-card-title>Card{{n + 6*(page-1)}}</v-card-title>
          </v-card>
        </v-col>
      </v-row>
    </v-container>
    <v-pagination
      v-model="page"
      length="50"
      total-visible="3"
    ></v-pagination>
  </v-container>
</template>
<script>
export default {
  data () {
    return {
      page: 1,
    }
  },
}
</script>

v-toolbarv-card などスタイルを指定できるコンポーネントに入れると、色を指定できるようになります。

image.png

コード;

App.vue
<template>
  <v-container>
    
    <v-container>
      <v-row>
        <v-col cols="3" v-for="n in 8" :key="n">
          <v-card height="200" color="secondary">
            <v-card-title>Card{{n + 6*(page-1)}}</v-card-title>
          </v-card>
        </v-col>
      </v-row>
    </v-container>
    <v-layout>
    <v-toolbar color="primary">
      <v-spacer></v-spacer>
      <v-pagination
        v-model="page"
        length="50"
        total-visible="5"
      ></v-pagination>
      <v-spacer></v-spacer>
    </v-toolbar>
    </v-layout>
  </v-container>
</template>
<script>
export default {
  data () {
    return {
      page: 1,
    }
  },
}
</script>

v-pagination 自体は、値を選ぶだけの機能のコンポーネントなので、値を選ぶ目的にも使えなくはないです。

最後ページまで飛ぶとか、最初ページまで戻るとか、そういう機能はまだないぽいです(ページ番号を指定して表示を強制的に変更することはできます)。多分、Beta 出なくなるころにはもうちょっと機能が追加されるはず・・・

そのほか便利なやつ

v-progress-circle / v-progress-linear

ロード中とかにぐるぐる回る表示をしたり、進行状況を表示したりできるコンポーネントです。

progress1.gif

コード:

App.vue
<template>
  <v-container>
    <v-progress-circular
      :indeterminate="loading"
      color="primary"
    ></v-progress-circular>

    <v-btn @click="loading = !loading" class="ma-3">
      Toggle
    </v-btn>
</v-container>
</template>
<script>
export default {
  data () {
    return {
      loading: false,
    }
  },
}
</script>

どのくらい進んでるかの進行度を表示する用途にも使えます。

progress2.gif

コード:

App.vue
<template>
  <v-container>
    <v-progress-circular
      :rotate="360"
      :size="100"
      :width="15"
      :model-value="value"
      color="primary"
    >
      {{ value }}
    </v-progress-circular>

    <v-btn @click="progress" class="ma-3">
      Progress
    </v-btn>
  </v-container>
</template>
<script>
export default {
  data () {
    return {
      value: 0
    }
  },
  methods: {
    progress()
    {
      this.value += 10;
      if ( this.value > 100 ){
        this.value = 0;
      }
    }
  }
}
</script>

v-progress-linear はバータイプのものです。

progress4.gif

コード:

App.vue
<template>
  <v-container>
    <v-progress-linear
      color="deep-purple accent-4"
      :indeterminate="loading"
      rounded
      height="6"
    ></v-progress-linear>

    <v-btn @click="loading = !loading" class="ma-3">
      Toggle
    </v-btn>

    <v-divider class="my-5"></v-divider>

    <v-progress-linear v-model="value">
    </v-progress-linear>
    {{ value }}

    <v-btn @click="progress" class="ma-3">
      Progress
    </v-btn>
  </v-container>
</template>
<script>
export default {
  data () {
    return {
      value: 0,
      loading: false
    }
  },
  methods: {
    progress()
    {
      this.value += 10;
      if ( this.value > 100 ){
        this.value = 0;
      }
    }
  }
}
</script>

仕切りに使える横線 v-divider

そのままです。HTMLの hr を美しくした感じです。厚みは thickness で指定します。リストとかカードの中の仕切りにも使えます。inset を指定すると、カードとかリストいっぱいに広がります。

image.png

App.vue
<template>
  <v-container>
    <p class="my-3">hogehoge hogehoge</p>
    <v-divider></v-divider>
    <p class="my-3">hogehoge hogehoge</p>
    <v-divider thickness="5"></v-divider>
    <v-card class="my-3" color="secondary">
      <v-card-title>Hoge Card</v-card-title>
      <v-divider inset></v-divider>
      <v-card-text>hogehoge hogehoge</v-card-text>
    </v-card>
    
    <v-list>
      <v-list-item>Hoge1</v-list-item>
      <v-list-item>Hoge2</v-list-item>
      <v-divider></v-divider>
      <v-list-item>Hoge3</v-list-item>
    </v-list>
    
  </v-container>
</template>

bar 系のコンポーネントで縦方向の仕切りにもできます。

image.png

コード

App.vue
<template>
<v-container>
  <v-toolbar>
    <v-toolbar-title>Title</v-toolbar-title>

    <v-divider
      class="mx-4"
      vertical
      thickness="4"
    ></v-divider>

    <v-btn>HOGE1</v-btn>

    <v-divider
      class="mx-4"
      vertical
    ></v-divider>

    <v-btn>HOGE2</v-btn>

  </v-toolbar>
</v-container>
</template>

シンプルですが、いろんなところの仕切りとしてかなり使えます。class="my-3" とかマージンを指定すると、縦方向の位置の微調整とかにも使えます。なお、水平の線の場合は横方向のマージン指定は無効です。

詳細は下記を見てください。

ツールバー v-toolbar

アプリケーションバー (v-app-bar) のように、ボタンとかアイコンとかを横n並べてバーのように表示できます。アプリケーションバーはアプリ内にひとつしか置けませんが、ツールバーはいくつでも置けます。また、v-layout も不要です。

下の例のように、ページ内に浮いているカードに着けたりできます。(アプリケーションバーは画面の上に常に張り付く)。

image.png

コード:

App.vue
<template>
  <v-card color="blue-lighten-4" width="80%" height="300" class="mx-auto my-3">
    <v-toolbar color="primary">
      <v-app-bar-nav-icon></v-app-bar-nav-icon>
      <v-toolbar-title>v-toolbar-title</v-toolbar-title>
      <v-btn>SignIn</v-btn>
      <v-btn icon="mdi-home"></v-btn>
    </v-toolbar>
  </v-card>
</template>

v-toolbar-title という要素がありますが、v-app-bar-title をつかっても同じ結果になります。将来的には `v-toolbar-title しかダメになるかもしれません。

v-paginationv-tabs など、通常では背景色を付けられないコンポーネントに色をつける目的にも使えます。

image.png

コード:

App.vue
<template>
  <v-toolbar color="primary" class="mx-2 my-3">
    <v-spacer></v-spacer>
    <v-pagination length="4">
    </v-pagination>
    <v-spacer></v-spacer>
  </v-toolbar>

  <v-toolbar color="secondary" class="mx-2 my-3">
    <v-spacer></v-spacer>
    <v-tabs>
      <v-tab>HOGE1</v-tab>
      <v-tab>HOGE2</v-tab>
      <v-tab>HOGE3</v-tab>
    </v-tabs>
    <v-spacer></v-spacer>
  </v-toolbar>
</template>

v-footer にボタンを横方向に配置したいときも、これを使うと楽です。

image.png

コード:

App.vue
<template>
  <v-app>
    <v-main>
      <v-container>
        Main Contents
      </v-container>
    </v-main>
    <v-footer app color="primary">
      <v-toolbar color="primary">
        <v-spacer></v-spacer>
        <v-btn icon="mdi-home"></v-btn>
        <v-btn icon="mdi-file"></v-btn>
        <v-btn icon="mdi-google"></v-btn>
        <v-spacer></v-spacer>
      </v-toolbar>
    </v-footer>
  </v-app>
</template>

色を指定するときは、v-footerv-toolbar の両方で同じ色を指定するようにします。

詳細は下記を見てください。

横方向の空白 v-spacer

横方向に並べられたコンポーネントの間に置くと、その位置に「めいっぱいの」横方向の空白を作ります。同じ行内に複数の v-spacer を置くと、`v-spacer ごとに同じだけの横幅が割り当てられます。

コンポーネントを d-flexv-row で横に並べているときや、v-app-bar-v-toolbar で横に並べているときに、コンポーネント間に空白を作りたいときや。コンポーネントを寄せるときに使います。

機能としては空白を置くだけなんですが、実質的にはコンポーネントを任意の位置に「寄せる」ためのパーツといってもよいでしょう。非常に汎用性が高いです。

image.png

たとえば上の図で、上の二つのような単純な寄せ方なら、v-spacer なしでも簡単です。しかし、下の二つのような寄せ方をしようとすると、v-spacer なしだと複雑になります。

App.vue
<template>
<v-container>

  <div class="d-flex justify-end">
    <v-btn>HOGE1</v-btn> 
    <v-btn>HOGE2</v-btn> 
    <v-btn>HOGE3</v-btn> 
  </div>

  <div class="d-flex justify-center my-3">
    <v-btn>HOGE1</v-btn> 
    <v-btn>HOGE2</v-btn> 
    <v-btn>HOGE3</v-btn> 
  </div>

  <div class="d-flex my-3">
    <v-spacer></v-spacer>
    <v-btn>HOGE1</v-btn> 
    <v-spacer></v-spacer>
    <v-btn>HOGE2</v-btn> 
    <v-spacer></v-spacer>
    <v-btn>HOGE3</v-btn> 
    <v-spacer></v-spacer>
  </div>

  <div class="d-flex my-3">
    <v-spacer></v-spacer>
    <v-btn>HOGE1</v-btn> 
    <v-spacer></v-spacer>
    <v-btn>HOGE2</v-btn> 
    <v-btn>HOGE3</v-btn> 
    <v-spacer></v-spacer>
  </div>
</v-container>
</template>

v-spacer は、v-radio ように、普通では mx-autod-flex justify-center がきかないコンポーネントでも寄せられます。上の行は d-flex justify-center をつけても中央によりませんが、v-spacer のあるほうは寄ります(中央の行)。

image.png

コード:

App.vue
<template>
  <v-container>
    <div class="d-flex justify-center">
        <v-radio-group>
          <div class="d-flex flex-row" >
            <v-radio label="Hoge1" value="1"></v-radio>
            <v-radio label="Hoge2" value="2"></v-radio>
            <v-radio label="Hoge3" value="3"></v-radio>
          </div>
        </v-radio-group>
    </div>

    <div class="d-flex">
      <v-spacer></v-spacer><!-- これを入れると中央に寄せられる -->
        <v-radio-group>
          <div class="d-flex flex-row" >
            <v-radio label="Hoge1" value="1"></v-radio>
            <v-radio label="Hoge2" value="2"></v-radio>
            <v-radio label="Hoge3" value="3"></v-radio>
          </div>
        </v-radio-group>
    </div>

    <div class="d-flex justify-end">
      <div><!-- ダミーの div を入れると右にも寄せられる -->
        <v-radio-group>
          <div class="d-flex flex-row" >
            <v-radio label="Hoge1" value="1"></v-radio>
            <v-radio label="Hoge2" value="2"></v-radio>
            <v-radio label="Hoge3" value="3"></v-radio>
          </div>
        </v-radio-group>
      </div>
    </div>
  </v-container>
</template>

これがバグなのか仕様なのかいまいちわかりませんが、v-radio は右側に無限のスペースが最初から挿入されているかにように振舞います。v-spacer を左側に挿入することで、右側に挿入されたスペースとバランスがとれて、中央によります。

ちなみにこの手のコンポーネントを右に寄せたい場合は、v-spacer だけでは無理です。三つ目の例のように、ダミーの div をはさむと寄るようになります。

v-col を寄せるときにも v-spacer 使えます。むしろ、大抵の場合は v-spacer で寄せるほうが楽です。なお、一行に含まれる cols の合計値が 12 未満のときでないと、v-spacer は無視されます。下の図の一番下の行は v-spacer を入れていますが、合計値が 12 になっているため、cols の値による寄せのほうが優先されています。

image.png

App.vue
<template>
  <v-container>
    <v-row>
      <v-spacer></v-spacer>
      <v-col cols="3">
        <v-btn>HOGE1</v-btn>
      </v-col>
      <v-col cols="3">
        <v-btn>HOGE2</v-btn>
      </v-col>
      <v-col cols="3">
        <v-btn>HOGE3</v-btn>
      </v-col>
    </v-row>

    <v-row>
      <v-spacer></v-spacer>
      <v-col cols="3">
        <v-btn>HOGE1</v-btn>
      </v-col>
      <v-col cols="3">
        <v-btn>HOGE2</v-btn>
      </v-col>
      <v-col cols="3">
        <v-btn>HOGE3</v-btn>
      </v-col>
      <v-spacer></v-spacer>
    </v-row>

    <v-row>
      <v-spacer></v-spacer><!-- cols の合計値が12だと無視される -->
      <v-col cols="4">
        <v-btn>HOGE1</v-btn>
      </v-col>
      <v-col cols="4">
        <v-btn>HOGE2</v-btn>
      </v-col>
      <v-col cols="4">
        <v-btn>HOGE3</v-btn>
      </v-col>
      <v-spacer></v-spacer>
    </v-row>
  </v-container>
</template>

v-spacerv-toolbarv-app-bar でのボタンやアイコンなどの間にスペースを入れるときにもよく使います。

image.png

コード:

App.vue
<template>
  <v-app>
    <v-app-bar color="primary">
      <v-app-bar-nav-icon></v-app-bar-nav-icon>
      <v-app-bar-title>
        v-space なし
      </v-app-bar-title>
      <v-btn>SignIn</v-btn>
      <v-btn icon="mdi-home"></v-btn>
    </v-app-bar>
  </v-app>
</template>

v-spacer を入れないと、上のような感じになります。v-app-bar-title の右側に自動的にスペースが入って、残りのコンポーネントは右に寄ります。

v-spacer を入れると、文字やボタンの位置を左右に動かせます。

image.png

コード:

App.vue
  <v-app>
    <v-app-bar color="primary">
      <v-app-bar-nav-icon></v-app-bar-nav-icon>
      <v-spacer></v-spacer>
      <v-app-bar-title>
        v-space あり
      </v-app-bar-title>
      <v-spacer></v-spacer>
      <v-btn>SignIn</v-btn>
      <v-btn icon="mdi-home"></v-btn>
    </v-app-bar>
  </v-app>
</template>

v-app-barv-toolbar の中では justify-centerms-auto が効かないので、寄せたい場合は v-spacer を使う必要があります。

結論

Directive については別途まとめる予定です。

29
21
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
29
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?