LoginSignup
25
25

More than 5 years have passed since last update.

Google Books APIとVue.jsを使ってシンプルなBook Finder appを作る

Last updated at Posted at 2019-03-30

このアプリを作ろうと思ったキッカケ

2月末にChingu Voyageという海外のプロジェクトに参加し、見事に制限時間内に課題のGoogle APIを使ったBook Finder アプリを作ることができずプロジェクトから落ちました。(笑)

というのも私はずっとrailsでしか勉強をしていなくてAPIはなんとなくJSONだったりaxiosが必要だということは分かっていたのですが、Javascriptを本格的に勉強したことがなく、プロジェクトでJavascriptが必要と分かった瞬間必死でネット上の教材を探したのですが、なかなか希望するものがなく・・・
いや写経してもなんの意味もないなと気づいたので、最近勉強をしているVue.jsを使って自分で作ってみようと思いました。

こんなアプリができます

↓こんなアプリが最終的にできます。Vue.jsだと直感的にコードが理解しやすく好きです。
Google books api app
※モバイルでみるとボタンの文字がおかしいですがまた調整します。

1 検索したい本の名前や、著者名を入力
スクリーンショット (438).png

2 本の名前、画像、著者名をapiから取得し、表示させる
スクリーンショット (436).png

3 SHOW DETAILボタンで、googlebooksのサイトに遷移し、本の詳細を見る
スクリーンショット (437).png

ソースコードと解説

main.js
const vm = new Vue({
  el: '#app',
  data() {
    return{
      query:'',
      items:[], #apiから取得したデータを格納
      }
    },
  methods:{
    getResult(query){
      axios.get("https://www.googleapis.com/books/v1/volumes?q=search" + query).then(response => {
        console.log(response.data);
        this.items = response.data.items;
        });
      }
    }
});

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Book Finder</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
    <link rel="stylesheet" href="main.css">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  </head>
  <body>
    <div class="container" id="app">
      <h3 class="text-center">Book Finder</h3>
      <p> Search:<form v-on:submit.prevent="getResult(query)">
        <input type="text" placeholder="Type in your search" v-model="query" /></p> #フォーム入力したものをv-modelでバインド
          <div class="book_wrapper">
            <div class="book_card" v-for="item in items">


              <div class="row no-gutters">
                <div class="col-md-4">
                  <img class="card-img" v-bind:src="item.volumeInfo.imageLinks.thumbnail" />
                </div>

                <div class="col-md-8">
                  <div class="card-body">
                    <h5 class="card-title">{{item.volumeInfo.title}}</h5>
                    <p class="card-text">{{item.volumeInfo.authors}}</p>    
                    <p class="card-text"><small class="text-muted">{{item.volumeInfo.publisher}}</small></p>    
                  </div>

                  <div class="book_button">
                    <a v-bind:href="item.volumeInfo.previewLink" class="waves-effect waves-light btn" target="_blank">show detail</a>
                  </div>
                </div>
          </div>
        </div>
       </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> #vue.jsのインストール
    <script src="main.js"></script> #jsファイルを読み込む
    <script src="https://cdn.jsdelivr.net/npm/axios@0.17.1/dist/axios.min.js"></script> #axiosをインストール
  </body>

</html>

main.css
.book_wrapper{
    width:100%;
}

.book_card{
    margin:10px;
    float:left;
    box-sizing: border-box;
    -webkit-box-sizing: border-box;
    width:40%;
}

.book_button{
    text-align:center;
}

参考知識

利用したVue.jsやaxiosについて下に参考メモを記入しておきます。

Vue.jsのインストール

CDNで用意されているので、index.htmlに貼り付けましょう。
詳しくはインストールを参照してください。

JSONデータとaxiosでgetしたデータについて

今回はGooglebooksAPIを利用してアプリを作りました。
ドキュメントはこちら

例えばURLに
https://www.googleapis.com/books/v1/volumes?q=search+harry このようにいれると、harryと名前がつくものを検索することができます。
これを検索欄に入力すると画面いっぱいに以下のようなJSONデータが表示されます。

{
 "kind": "books#volumes", //books#volumesの種類で検索
 "totalItems": 561, //561個のデータがある
 "items": [  //そのうちのitemsは以下のとおり
  {
   "kind": "books#volume",
   "id": "8VEJo-StWrkC",
   "etag": "n0F3h00LHMo",
   "selfLink": "https://www.googleapis.com/books/v1/volumes/8VEJo-StWrkC",
   "volumeInfo": {
    "title": "The Search for Harry C", //タイトル
    "authors": [
     "Mort Altshuler & Irv Susson" //著者
    ],
    "publisher": "Xlibris Corporation", //発刊者
    "publishedDate": "2001-05-14", //発刊日
    "description": "Harry Connors is at Penn State and in love with Sarah, a fellow student. They marry shortly after they are graduated. He gets a job with a contract agency of the Atomic Energy Commission involved in research programs related to atom bomb radiation effects, trigger devices and other secret projects. Harry´s work takes him to New Mexico, Philadelphia Naval Air Station and Indian Springs Air Force Base, Nevada. On the day that Harry disappears, a test atom bomb is detonated, an unmanned plane flown near the mushroom cloud to collect data explodes and a top-secret plan goes missing. Harry is never found and the government´s investigation circumstantially determines that Harry was an agent of the Soviet Union. Sarah, pregnant, returns to Pennsylvania. Four decades later, Harry´s son, Adam, sets out on an intriguing mission to find out what happened to his father. Along the way, with the help of his fiancee and two of his father´s fraternity brothers, he finds an aged member of the Russian spy machine, ex coworkers and a host of some very odd folks.", //本の説明
    "industryIdentifiers": [
     {
      "type": "ISBN_13",
      "identifier": "9781465315236"
     },
     {
      "type": "ISBN_10",
      "identifier": "1465315233"
     }
    ],
    "readingModes": {
     "text": true,
     "image": true
    },
    "pageCount": 211,
    "printType": "BOOK",
    "categories": [
     "Fiction"
    ],
    "maturityRating": "NOT_MATURE",
    "allowAnonLogging": false,
    "contentVersion": "0.1.0.0.preview.3",
    "panelizationSummary": {
     "containsEpubBubbles": false,
     "containsImageBubbles": false
    },
    "imageLinks": { //smallThumbnailとthumbnailはどちらも画像を表示する
     "smallThumbnail": "http://books.google.com/books/content?id=8VEJo-StWrkC&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api",
     "thumbnail": "http://books.google.com/books/content?id=8VEJo-StWrkC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api"
    },
    "language": "en",
    "previewLink": "http://books.google.co.jp/books?id=8VEJo-StWrkC&pg=PA69&dq=search+harry&hl=&cd=1&source=gbs_api", //今回は詳細ページをこちらにします。
    "infoLink": "https://play.google.com/store/books/details?id=8VEJo-StWrkC&source=gbs_api",
    "canonicalVolumeLink": "https://market.android.com/details?id=book-8VEJo-StWrkC"
   }, //ここから下はこのアプリでは使わない情報です。
   "saleInfo": {
    "country": "JP",
    "saleability": "FOR_SALE",
    "isEbook": true,
    "listPrice": {
     "amount": 1404.0,
     "currencyCode": "JPY"
    },
    "retailPrice": {
     "amount": 1264.0,
     "currencyCode": "JPY"
    },
    "buyLink": "https://play.google.com/store/books/details?id=8VEJo-StWrkC&rdid=book-8VEJo-StWrkC&rdot=1&source=gbs_api",
    "offers": [
     {
      "finskyOfferType": 1,
      "listPrice": {
       "amountInMicros": 1.404E9,
       "currencyCode": "JPY"
      },
      "retailPrice": {
       "amountInMicros": 1.264E9,
       "currencyCode": "JPY"
      }
     }
    ]
   },
   "accessInfo": {
    "country": "JP",
    "viewability": "PARTIAL",
    "embeddable": true,
    "publicDomain": false,
    "textToSpeechPermission": "ALLOWED",
    "epub": {
     "isAvailable": true,
     "acsTokenLink": "http://books.google.co.jp/books/download/The_Search_for_Harry_C-sample-epub.acsm?id=8VEJo-StWrkC&format=epub&output=acs4_fulfillment_token&dl_type=sample&source=gbs_api"
    },
    "pdf": {
     "isAvailable": true,
     "acsTokenLink": "http://books.google.co.jp/books/download/The_Search_for_Harry_C-sample-pdf.acsm?id=8VEJo-StWrkC&format=pdf&output=acs4_fulfillment_token&dl_type=sample&source=gbs_api"
    },
    "webReaderLink": "http://play.google.com/books/reader?id=8VEJo-StWrkC&hl=&printsec=frontcover&source=gbs_api",
    "accessViewStatus": "SAMPLE",
    "quoteSharingAllowed": false
   },
   "searchInfo": {
    "textSnippet": "They did \u003cb\u003efind\u003c/b\u003e a small cave at Spectre Mountain about three hundred feet up. It \u003cbr\u003e\nwas only about four feet high and about seven feet deep and it looked as though \u003cbr\u003e\nit may have been a burial site. It was obvious that it had been searched and \u003cbr\u003e\nruined&nbsp;..."
   }
  },

v-modelで検索フォームで入力した文字をデータとして渡す

基本的な使い方としては以下のような形があります。入力や選択をすると、即座にデータ、そしてDOMに反映されます。今回はこちらを利用して検索フォームに入力した言葉をmain.jsのmethodsに渡しています。

(参考)

html
  <p>{{message}}</p>
  <input v-model="message">
javascript
var app = new Vue({
   el: '#app'
   data:{
      message:'メッセージ'
    }
})

レスポンシブ対応

【CSS】box-sizing:border-boxの使い方|効かない時は?
以前からレスポンシブ対応に苦手意識がありましたが、今回box-sizingを利用して非常に楽に設定できるようになりました。

デザイン

materializecssBootstrapが混在してしまいました。
が、まあいっかという感じです。
このようなデザインフレームワークを使うと自動でレスポンシブになるので好きです。足りないところをプラスすればいいです。

疑問点・理解しきれていないこと

検索結果がすべて表示されないこと

APIから取得したデータはかなり多いはじなのに、1ページしか表示されません。なぜかまだ調べてみます。

var app と const vm の違い

Vue.jsを表面上しか分かった気になっていないため、このような違いに混乱します。
違いについて検索してみると、var appもあればconst vmもあり、どっちも使えるが、constは読み取り専用となり、再代入ができない等の理由がある・・・とのこと。まだ理解しておりません。

v-on と v-modelの違い

公式リファレンス:イベントハンドリングフォーム入力バインディングを参照してみると、v-onの場合はクリックしたりラジオボタンを押したりすることで、イベントを発生させる場合に使用する、v-modelの場合は、フォームに入力した文字等を非同期で反映させたいときに使用するという使い分けかなと思います。

今回参考にしたサイト

Vue.jsでQiita検索APIを使ってみる
Vue.jsとAxiosなら驚くほど簡単に作れる!外部APIを使ったWebアプリの実例
TypeScriptでNuxtアプリを作るチュートリアル【書籍検索システム】

間違っている記述やもっとこうしたほうがいいとのご意見等ありましたらコメントください。

25
25
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
25
25