20
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Vuetify と Vue Router でレスポンシブなナビゲーションを作ってみました

Posted at

はじめに

最初に作ったものを載せておきます。

デモ

vuetify.gif

コード

事前準備

VueCLI3 のインストールを行なってください

【Vue】プロジェクトの作成

terminal
$ vue create vuetify-vuerouter-navbar-example

いくつか質問が表示されるので

  • Manually select features を選択肢し
  • Router を追加してください

その他はお好みでどうぞ

terminal
Vue CLI v3.7.0
┌───────────────────────────┐
│  Update available: 3.8.2  │
└───────────────────────────┘
? Please pick a preset:
  default (babel, eslint)
❯ Manually select features
terminal
? Please pick a preset: Manually select features
? Check the features needed for your project:
 ◉ Babel
 ◯ TypeScript
 ◯ Progressive Web App (PWA) Support
❯◉ Router
 ◯ Vuex
 ◯ CSS Pre-processors
 ◉ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing

Vuetify を追加

プロジェクト直下に移動し Vuetify をインストールします。

terminal
$ cd vuetify-vuerouter-navbar-example
$ vue add vuetify

preset は Default (recommended)を選択してください

terminal
? Choose a preset:
❯ Default (recommended)
  Prototype (rapid development)
  Configure (advanced)

サーバを起動

terminal
$ yarn serve

http://localhost:8080/ をブラウザで開いて
Welcome to Vuetify の文字が出てくれば OK です

Screen Shot 2019-05-29 at 10.34.49.png

プロジェクトを確認

plugins ディレクトリに vuetify.js が作られていて
それを main.js でインポートしているようです。

src/plugins/vuetify.js
import Vue from "vue";
import Vuetify from "vuetify/lib";
import "vuetify/src/stylus/app.styl";

Vue.use(Vuetify, {
  iconfont: "md"
});
src/main.js
import Vue from "vue";
import "./plugins/vuetify";

// ... 略

コンポーネントの作成

ここからいよいよ本題です。
Header.vue を作成しナビゲーションの内容を記述します。

src/components/Header.vue
<template>
  <div>
    <v-navigation-drawer v-model="drawer" absolute temporary>
      <v-list class="pa-1">
        <v-list-tile avatar>
          <v-list-tile-avatar>
            <img src="https://randomuser.me/api/portraits/men/85.jpg" />
          </v-list-tile-avatar>
          <v-list-tile-content>
            <v-list-tile-title>John Leider</v-list-tile-title>
          </v-list-tile-content>
        </v-list-tile>
      </v-list>
      <v-list>
        <v-text-field
          clearable
          flat
          label="Search"
          prepend-inner-icon="search"
          solo
          single-line
          hide-details
        ></v-text-field>
      </v-list>
      <v-list class="pt-0" dense>
        <v-divider></v-divider>
        <v-list-tile v-for="item in items" :key="item.title" :to="item.to">
          <v-list-tile-action>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-tile-action>
          <v-list-tile-content>
            <v-list-tile-title>{{ item.title }}</v-list-tile-title>
          </v-list-tile-content>
        </v-list-tile>
      </v-list>
    </v-navigation-drawer>
    <v-toolbar dark color="primary" clipped-left fixed app>
      <v-toolbar-side-icon
        @click.stop="drawer = !drawer"
        class="hidden-md-and-up"
      ></v-toolbar-side-icon>
      <v-toolbar-title class="headline text-uppercase white--text">
        <span>Vuetify</span>
        <span class="font-weight-light">MATERIAL DESIGN</span>
      </v-toolbar-title>
      <v-spacer></v-spacer>
      <v-expand-x-transition>
        <v-text-field
          class="hidden-sm-and-down"
          clearable
          flat
          label="Search"
          prepend-inner-icon="search"
          solo-inverted
          single-line
          hide-details
          v-show="showSearchInput"
        ></v-text-field>
      </v-expand-x-transition>
      <v-toolbar-items class="hidden-sm-and-down">
        <v-btn icon @click="showSearchInput = !showSearchInput">
          <v-icon>search</v-icon>
        </v-btn>
        <v-btn flat to="/">Home</v-btn>
        <v-btn flat to="/about">About</v-btn>
      </v-toolbar-items>
    </v-toolbar>
  </div>
</template>

<script>
export default {
  name: "Header",
  data() {
    return {
      drawer: null,
      showSearchInput: false,
      items: [
        { title: "Home", icon: "dashboard", to: "/" },
        { title: "About", icon: "question_answer", to: "/about" }
      ]
    };
  }
};
</script>

ナビゲーションとサイドパネル

下記を参考にしました。

アニメーション

<v-expand-x-transition>で検索 box の表示切替のときにアニメーションを付けています。

v-expand-x-transition
<v-expand-x-transition>
  <v-text-field
    class="hidden-sm-and-down"
    clearable
    flat
    label="Search"
    prepend-inner-icon="search"
    solo-inverted
    single-line
    hide-details
    v-show="showSearchInput"
  ></v-text-field>
</v-expand-x-transition>

ブレークポイント

hidden-md-and-up と
hidden-sm-and-down
で画面サイズによって表示切替をするブレークポイントをつけています。

hidden-md-and-up
<v-toolbar-side-icon
  @click.stop="drawer = !drawer"
  class="hidden-md-and-up"
></v-toolbar-side-icon>
hidden-sm-and-down
<v-toolbar-items class="hidden-sm-and-down">
  <v-btn icon @click="showSearchInput = !showSearchInput">
    <v-icon>search</v-icon>
  </v-btn>
  <v-btn flat to="/">Home</v-btn>
  <v-btn flat to="/about">About</v-btn>
</v-toolbar-items>

App.js で Header.vue を呼び出す

src/App.vue
<template>
  <v-app>
    <Header />
    <v-content>
      <v-container fluid fill-height>
        <v-layout justify-center align-center>
          <router-view></router-view>
        </v-layout>
      </v-container>
    </v-content>
  </v-app>
</template>

<script>
import Header from "@/components/Header";
export default {
  name: "App",
  components: {
    Header
  }
};
</script>

さて、完成したので再度 http://localhost:8080/ へアクセスして確認してみましょう
こんな表示になっていれば OK です。
Screen Shot 2019-05-29 at 12.30.24.png

おわりに

最後まで読んでいただきありがとうございました。
Vuetify は Theme も公開されているようですね
中には無料の物もあるようなので試してみてはいかがでしょうか
Free / Premium Themes — Vuetify.js

Vue.js は至れり尽くせりですね 😁

20
17
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
20
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?