vue-cliとVuetifyを使って映画情報検索サイトを作る

vue-cliで開発する練習?の一環で非常にシンプルな映画情報検索サイトを作ってみたのでフロントエンドのコンポーネントの作り込みについてまとめます。
デザインのフレームワークとしてVuetifyを使用しています。

# 開発環境
・フロントエンド
npm:6.12.1
node:12.13.1
yarn:1.21.1
Vue-cli:4.1.1
Vuetify:2.2.3


# 参考

[無料で映画情報を取得するAPI「TMDb」の使い方](https://weblion303.net/1262/)
[【vue.js】Vuefityをマスターする(1)](https://reffect.co.jp/vue/vuetify-for-beginner)


# アプリケーションの動きについて

画面にアクセスした直後は検索欄が表示されます。

![スクリーンショット 2020-02-27 23.14.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238861/ef436e95-e8bc-a0a1-848b-b3c7378462f6.png)

セレクトボックスにフォーカスを入れると最近上映されている映画のタイトルが選択出来るようになっています。
このセレクトボックスのデータは画面描画時にバックエンドへのAPIリクエストで取得しています。


![スクリーンショット 2020-03-03 23.20.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238861/18de4e63-0af1-3d4a-85f0-95a3c4968e0e.png)


試しに「ジョーカー」を選択すると、右下の「SEARCH」と書かれている検索ボタンが有効化され押下出来るようになります。


![スクリーンショット 2020-03-03 23.22.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238861/f3cc912d-d797-eb12-b1e1-9d1a5fa57599.png)



検索ボタンを押下するとバックエンドへのリクエストが行われ、選択したタイトルに合致する映画の情報を画面に描画します。
*画像が登録されていない映画はデフォルト用の画像を設定し、タイトル末尾に(No Image)と追記しています。


![スクリーンショット 2020-03-03 23.23.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238861/fb955cfa-979b-6d27-7cd5-1367fd7d3f7a.png)



セレクトボックスに格納されているタイトルだけでなく任意に入力したタイトルでも検索することが出来ます。
試しに「１２３」と入力し検索ボタンを押下してみます。







「１２３」に合致する映画の情報を全て取得して来てくれます。
*画像が登録されていない映画はデフォルト用の画像を設定し、タイトル末尾に(No Image)と追記しています。

![スクリーンショット 2020-03-03 23.12.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238861/a541e8a3-9ff2-fe8f-0285-d5bd3077c699.png)






# コンポーネントについて

画面を構成しているコンポーネントは以下の通りです。

## メインのコンポーネント

画面全体のコンポーネントです。

検索欄のカードはCardMovieSearchコンポーネントという子コンポーネントで構成されています。
セレクトボックスの値のget,setを共に親コンポーネントでチェックしたい為セレクトボックスのタグ(v-comboboxタグ)のみslotで子コンポーネントで渡しています。

検索された映画情報はCardMovieInfoコンポーネントという子コンポーネントに出力します。


```HTML
  <v-layout text-center wrap>
    <v-flex xs12 v-if="errorFlag">
      <v-alert type="error">
        {{ errorMessage }}
      </v-alert>
    </v-flex>

    <v-flex mb-5 xs12>
      <CardMovieSearch
        :disabledFlag="noInputFlag"
        @searchEvent="showMovieInfo($event)"
      >
        <template>
          <v-combobox
            v-model="getSelectData"
            :items="getTitlesList"
            label="Input Movie Title"
            outlined
            dense
            small-chips
          />
        </template>
      </CardMovieSearch>
    </v-flex>

    <v-flex xs12 v-if="searchFlag">
      <CardMovieInfo
        v-for="movie in getMoviesData"
        v-bind:key="movie.id"
        :movieData="movie"
      />
    </v-flex>
  </v-layout>
```

## CardMovieSearchコンポーネント

検索欄のコンポーネントです。
v-btnタグのclieckイベントではaxiosによるGETリクエストの処理を行います。
GETリクエストに成功すればCardMovieInfoコンポーネントの表示フラグをtrueにします。

```HTML
  <v-card class="mx-auto text-center" color="gray" dark outlined>
    <v-card-title class="text-right">
      <div class="display-1 font-weight-thick">Movie Search!</div>
    </v-card-title>
    <v-card-text>
      <div class="display-1 font-weight-thick">Movie Info Search Servise</div>
      <v-row>
        <v-col cols="12">
          <slot/>
        </v-col>
      </v-row>
      <v-card-actions>
        <v-spacer/>
        <v-btn
         class="success"
         large="true"
         color="orange"
         disabled="true"
         text
         @click="startSearch()"
        >
         Search!
         <v-icon dark right>mdi-database-search</v-icon>
        </v-btn>
      </v-card-actions>
    </v-card-text>
  </v-card>
```

## CardMovieInfoコンポーネント

各映画情報を出力する為のコンポーネントです。
v-imgタグではTMDBの画像を出力する為に画像出力用のURLもsrc属性に記載しています。

```HTML
  <v-card class="mx-auto" max-width="400" hover>
    <v-img
      v-if="movieData.poster_path !== null"
      class="white--text align-end"
      height="200px"
      :src="'https://image.tmdb.org/t/p/original'+movieData.poster_path"
    >
      <v-card-title>{{ movieData.title }}</v-card-title>
    </v-img>
    <v-img
      v-else
      class="white--text align-end"
      height="200px"
      src="./../../assets/img/camera.png"
      alt="イメージポスター画像"
    >
      <v-card-title>{{ movieData.title }}</v-card-title>
    </v-img>

    <v-card-subtitle class="pb-0">Release: {{ movieData.release_date }}</v-card-subtitle>

    <v-card-text class="text--primary">
      <div>Original Title: {{ movieData.original_title }}</div>
      <div>{{ movieData.overview }}</div>
    </v-card-text>

    <v-card-actions>
      <v-btn color="orange" text>detail</v-btn>
    </v-card-actions>
  </v-card>
```

# 終わりに
コンポーネントの作り込みについては以上です。
Vuetifyを利用したおかげでCSSを使うことなく最低限のデザインの画面を作ることが出来ました。
再利用出来るコンポーネントを作るとプロジェクトを跨いでも使える為、画面設計の際には共通して利用出来る箇所が無いかに注意していきたいです。