LoginSignup
32
30

More than 3 years have passed since last update.

vue-cli + vuetify + vue-routerで映画お気に入りサイトの作成[画面作成編]

Last updated at Posted at 2019-07-23

普段業務でReactを触っているのですが、Vueは少ししか触ったことがなかったので、簡単なサイト作成をしながら勉強していこうと思います。

手順をずらずら書いているだけですが、誰かの役に立てれば幸いです。

今回の記事では以下の記事のような動きをする部分まで作成していきます。

test.mov.gif

Vue CLIをインストール

Nodeがインストールされている前提で進めていきます。

$ npm install -g @vue/cli
$ vue --version
3.9.2

無事に最新バージョンがインストールされました。

プロジェクトの作成

作りたいアプリケーション名でプロジェクトを作成します。
今回、お気に入りの映画を登録するアプリを作りたいので、favorite-movieというプロジェクト名にしました。

$ vue create favorite-movie(好きなプロジェクト名)

プリセットを選んでください、と言われた場合はdefaultで良いかと思います。

$ cd favorite-movie
$ ls
README.md       package-lock.json   src
babel.config.js     package.json
node_modules        public

無事にプロジェクトの作成がされました。

VuetifyとVue Routerのインストール

次に必要なライブラリを入れていきます。
今回は、Vue Router と Vuetifyを使用していきます。

Vue Routerは、ルーティングが出来るライブラリ。
Vuetifyは、マテリアルデザインを簡単に構築できるコンポーネントです。

$ vue add vuetify
$ npm install vue-router

でvuetifyとVue Routerをインストールします。
インストールが終了したら、サーバを立ち上げて表示を確認します。

$ npm run serve
 App running at:
  - Local:   http://localhost:8080/
  - Network: http://.........:8080/

ローカルサーバーが立ち上がり、URLが表示されます。
ブラウザで確認すると以下の画像のようになります。

スクリーンショット 2019-07-07 11.41.56.png

仮の画面を作成

ここまで確認できたら、実際に画面を作成していきます。
まずはルーティングで仮の画面を作成してきます。
・ホーム画面
・一覧画面
の2つを作成していきます。

src/components/Home.vue
<template>
  <v-container>
    <h1>ホーム画面</h1>
    <router-link to="/list">Go to List</router-link>
  </v-container>
</template>
src/components/List.vue
<template>
  <v-container>
    <h1>一覧画面画面</h1>
    <router-link to="/">Go to Home</router-link>
  </v-container>
</template>

ルーティングの作成

routes/index.jsを作成して、以下の内容を記述します。

src/router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import Home from './components/Home';
import List from './components/List';

Vue.use(Router);

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/list',
      name: 'list',
      component: List
    }
  ]
});

main.jsに追記します。

src/main.js
import Vue from 'vue';
import './plugins/vuetify';
import App from './App.vue';
import router from './router'; // 追記

Vue.config.productionTip = false;

new Vue({
  router, // 追記
  render: h => h(App)
}).$mount('#app');

最後にApp.vueを以下のようにします。

src/App.vue
<template>
  <v-app>
    <v-toolbar app>
      <v-toolbar-title class="headline text-uppercase">
        <span>Vuetify</span>
        <span class="font-weight-light">MATERIAL DESIGN</span>
      </v-toolbar-title>
      <v-spacer></v-spacer>
      <v-btn flat href="https://github.com/vuetifyjs/vuetify/releases/latest" target="_blank">
        <span class="mr-2">Latest Release</span>
      </v-btn>
    </v-toolbar>

    <v-content>
      <router-view />
    </v-content>
  </v-app>
</template>

ここまでで以下のようになると思います。
リンクをクリックしてページが切り替わることが確認できました。

スクリーンショット 2019-07-09 2.24.10.png

ヘッダー部分の編集

App.vueに書いてあるヘッダー部分を編集します。
App.vueの見通しが悪くなるので、Headerコンポーネントに分けていきたいと思います。
src/components/Header/index.vueを作成し、ヘッダー部分を移植します。

src/components/Header/index.vue
<v-toolbar app>
  <v-toolbar-title class="headline text-uppercase">
    <span>Vuetify</span>
    <span class="font-weight-light">MATERIAL DESIGN</span>
  </v-toolbar-title>
  <v-spacer></v-spacer>
  <v-btn flat href="https://github.com/vuetifyjs/vuetify/releases/latest" target="_blank">
    <span class="mr-2">Latest Release</span>
  </v-btn>
</v-toolbar>

App.vueを修正

src/App.vue
<template>
  <v-app>
    <Header />
    <v-content>
      <router-view />
    </v-content>
  </v-app>
</template>

<script>
import Header from "./components/Header";
export default {
  components: { Header }
};
</script>

コンポーネントが分かれて見やすくなったと思います。

次に、新規登録、ログインモーダルを作成していきたいと思います。
モーダルは以下のリンクにAPIの記述があります。
https://vuetifyjs.com/ja/components/dialogs

新規登録画面

src/components/Header/Signup.vue
<template>
  <v-dialog v-model="dialog" max-width="600px">
    <template v-slot:activator="{ on }">
      <v-btn round flat large color="primary" v-on="on">新規登録</v-btn>
    </template>
    <v-card>
      <v-card-title>
        <span class="headline">新規登録</span>
        <v-spacer></v-spacer>
        <v-btn icon @click="dialog = false">
          <v-icon>close</v-icon>
        </v-btn>
      </v-card-title>
      <v-card-text>
        <v-container grid-list-md>
          <v-layout wrap>
            <v-flex xs12>
              <v-text-field label="ユーザー名" required></v-text-field>
            </v-flex>
            <v-flex xs12>
              <v-text-field label="メールアドレス" required></v-text-field>
            </v-flex>
            <v-flex xs12>
              <v-text-field label="パスワード" type="password" required></v-text-field>
            </v-flex>
          </v-layout>
        </v-container>
      </v-card-text>
      <v-card-actions>
        <v-container grid-list-md>
          <v-btn block color="success" dark @click="dialog = false">登録</v-btn>
        </v-container>
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<script>
export default {
  data() {
    return {
      dialog: false
    };
  }
};
</script>

ログイン画面

src/components/Header/Signup.vue
<template>
  <v-dialog v-model="dialog" max-width="600px">
    <template v-slot:activator="{ on }">
      <v-btn round flat large v-on="on">ログイン</v-btn>
    </template>
    <v-card>
      <v-card-title>
        <span class="headline">ログイン</span>
        <v-spacer></v-spacer>
        <v-btn icon @click="dialog = false">
          <v-icon>close</v-icon>
        </v-btn>
      </v-card-title>
      <v-card-text>
        <v-container grid-list-md>
          <v-layout wrap>
            <v-flex xs12>
              <v-text-field label="メールアドレス" required></v-text-field>
            </v-flex>
            <v-flex xs12>
              <v-text-field label="パスワード" type="password" required></v-text-field>
            </v-flex>
          </v-layout>
        </v-container>
      </v-card-text>
      <v-card-actions>
        <v-container grid-list-md>
          <v-btn block color="success" dark @click="dialog = false">ログイン</v-btn>
        </v-container>
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<script>
export default {
  data() {
    return {
      dialog: false
    };
  }
};
</script>

ヘッダーコンポーネントに埋め込みます。

src/components/Header/index.vue
<template>
  <v-toolbar app>
    <v-toolbar-title class="headline text-uppercase">
      <span class="font-weight-light">Favorite Movie</span>
    </v-toolbar-title>
    <v-spacer></v-spacer>
    <Login />
    <Signup />
  </v-toolbar>
</template>

<script>
import Signup from "./Signup";
import Login from "./Login";
export default {
  components: { Signup, Login }
};
</script>

ここまでで以下の画像の通りになります。

スクリーンショット 2019-07-16 2.24.16.png

バリデーションの追加

新規登録画面にバリデーションを追加していきます。
スター数も多いVeeValidateを使用していこうと思います。
https://baianat.github.io/vee-validate/

以下のコマンドをターミナル上で実行して、インストールします。

$ npm install vee-validate --save

main.jsにVeeValideteをインポートします。
ついでに日本語のエラーメッセージが良いので、言語ファイルもインポートしておきます。

src/main.js
import Vue from 'vue';
import VeeValidate, { Validator } from 'vee-validate'; // 追加
import ja from 'vee-validate/dist/locale/ja'; // 追加
import './plugins/vuetify';
import App from './App.vue';
import router from './router';

Vue.config.productionTip = false;
Vue.use(VeeValidate); // 追加
Validator.localize('ja', ja); // 追加

new Vue({
  router,
  render: h => h(App)
}).$mount('#app');

あとは新規登録モーダルのフォーム部分を以下のように変更し、スクリプトを書き加えるとバリデーションが適応されます。

src/components/Header/Signup.vue
<!-- フォーム部分 -->
<v-card-text>
  <v-container grid-list-md>
    <v-layout wrap>
      <v-flex xs12>
        <v-text-field
          v-model="name"
          v-validate="'required'"
          data-vv-name="ユーザー名"
          :error-messages="errors.collect('ユーザー名')"
          label="ユーザー名"
        />
      </v-flex>
      <v-flex xs12>
        <v-text-field
          v-model="email"
          v-validate="'required|email'"
          data-vv-name="メールアドレス"
          :error-messages="errors.collect('メールアドレス')"
          label="メールアドレス"
        />
      </v-flex>
      <v-flex xs12>
        <v-text-field
          type="password"
          v-model="password"
          v-validate="'required|alpha_num|min:6'"
          data-vv-name="パスワード"
          :error-messages="errors.collect('パスワード')"
          label="パスワード"
        />
      </v-flex>
    </v-layout>
  </v-container>
</v-card-text>
src/components/Header/Signup.vue
<script>
// スクリプト部分
export default {
  data() {
    return {
      name: "",
      email: "",
      password: "",
      dialog: false
    };
  },

  methods: {
    async signup() {
      if (await this.$validator.validateAll()) {
        this.dialog = false;
        this.name = this.email = this.password = "";
        this.$validator.reset();
        this.$router.push("/list");
      }
    }
  }
};
</script>

バリデーションに成功していたら、一覧URLに飛ばすようにしました。
以下の画像のように、エラーメッセージも日本語になっていますね!

スクリーンショット 2019-07-20 12.39.16.png

ここまでの動作が確認できたら、ログイン画面も同じように実装します。
コードはGithubにあげますので、省略します!

あとは、ホーム画面と一覧画面をコンポーネントを組み合わせて作成します。
作成後のコードもGitにあげておきます!

次回はFirebaseを使用してログイン機能を実装したりする予定です。

32
30
1

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
32
30