【Vue.js】GoogleBookApiをlocalStorageに保存する。


# 概要
[【 Vue.js】Vue.jsでGoogleBookAPIを取得する。](https://qiita.com/Quest_love33/items/df2dbfa0d8de838267e1)で書いたデータをlocalstorageに保存します。
次回以降Vue CLIで一つのアプリケーションにしたいと思います。


[公式リファレンス](https://jp.vuejs.org/v2/cookbook/client-side-storage.html#%E8%A4%87%E9%9B%91%E3%81%AA%E5%80%A4%E3%82%92%E6%89%B1%E3%81%86)の情報をもとに作成します。


## case

[【 Vue.js】Vue.jsでGoogleBookAPIを取得する。](https://qiita.com/Quest_love33/items/df2dbfa0d8de838267e1)で最終的にsearchResultsという配列にjsonデータを取得しました。

* 取得したデータ
    * title
    * image
    * description

取得したデータをlocalStorageに保存します。


まずは公式リファレンスの[複雑な値をつかう]
(https://jp.vuejs.org/v2/cookbook/client-side-storage.html#%E8%A4%87%E9%9B%91%E3%81%AA%E5%80%A4%E3%82%92%E6%89%B1%E3%81%86)の確認。

* 
* 削除：Removeボタンを押すとremoveCat(n)関数が実行される。nは配列番号


```html
<div id="app">
  <h2>Cats</h2>
  <div v-for="(cat, n) in cats">
    <p>
    
      <span class="cat">{{ cat }}</span>
       <!-- 削除：Removeボタンを押すとremoveCat(n)関数が実行される。nは配列番号 -->
      <button @click="removeCat(n)">Remove</button>
    </p>
  </div>

  <p>

    <input v-model="newCat">
    <!-- 取得：Add CatボタンでaddCat関数を実行 -->
    <button @click="addCat">Add Cat</button>
  </p>

</div>
```



```js
const app = new Vue({
  el: '#app',
  data: {
    cats: [],//取得したデータの格納先
    newCat: null //入力データの格納先
  },
  mounted() { //vueインスタンスがマウントした後に実行
    if (localStorage.getItem('cats')) { //ストレジのkeyを検索
      try { //json -> stringに変換
        this.cats = JSON.parse(localStorage.getItem('cats'));
      } catch(e) { //データに問題があった場合に削除
        localStorage.removeItem('cats');
      }
    }
  },
  methods: {
    addCat() {
      // 実際に何かしたことを入力する
      if (!this.newCat) {
        return;
      }

      this.cats.push(this.newCat);//入力データを配列に追加
      this.newCat = ''; //入力欄を空に
      this.saveCats(); //ストレジに保存
    },
    removeCat(x) { //削除
      this.cats.splice(x, 1); //引数xから受け取った配列番号から1つ削除
      this.saveCats(); //ストレジに保存
    },
    saveCats() { //保存
      const parsed = JSON.stringify(this.cats);　//string -> json変換
      localStorage.setItem('cats', parsed); //cats配列へ保存
    }
  }
})
```

結構シンプルでわかりやすいですね。
これを少し修正して作ります。


## 完成したもの

* 今回は保存のみに焦点を当てているので保存したものの削除、一覧、編集は含めていません。

すなわち以下の要素は削除しています。
* removeCat(x)
* mounted()

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <input type="text" v-model="keyword" />
      <button @click="Saerch(keyword)">検索</button>
      <div>
        <ul>
            <li v-for="(book, index) in saerchResults" :key="index">
                {{ book.title }}
                <!-- bookオブジェクトを渡している。 -->
                <button @click="addBook(book)">追加</button>
            </li>
        </ul>
      
      </div>
     
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
    <script>
      let app = new Vue({
        el: "#app",
        data() {
          return {
            keyword: "",
            saerchResults: [], //検索結果の一覧
            books:[] //追加したデータの格納先
          };
        },
        methods: {
          //クエリストリングの作成
          async Saerch(keyword) {
            //初期化
            this.saerchResults = [];
            const baseUrl = "https://www.googleapis.com/books/v1/volumes?";
            const params = {
              q: `intitle:${keyword}`,
              maxResults: 40,
            };
            const queryParams = new URLSearchParams(params);
            console.log(baseUrl + queryParams);

            //fetchでjson取得
            const response = await fetch(baseUrl + queryParams)
              //responseをjsonに変換
              .then((response) => response.json())
              .then(console.log());
            for (let book of response.items) {
              //jsonオブジェクトのtitle,imageLinks, descriptionまでアクセス
              let title = book.volumeInfo.title;
              let img = book.volumeInfo.imageLinks
                ? book.volumeInfo.imageLinks
                : "";
              let description = book.volumeInfo.description;
              //必要な情報をpush, title情報なければ空を追加
              this.saerchResults.push({
                title: title ? title : "",
                image: img.thumbnail ? img.thumbnail : "",
                //40文字以内
                description: description ? description.slice(0, 40) : "",
              });
            }
          },
          addBook(book) {
            this.books.push(book); //bookオブジェクトを受け取る。
            this.saveBooks();
          },
          saveBooks() {
            const parsed = JSON.stringify(this.books); //文字列 ->json
            localStorage.setItem('books', parsed); //第一引数：keyの名前,第二引数：value
          },
        },
      });
    </script>
  </body>
</html>

```

![ezgif.com-gif-maker (7).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/8a88ddf4-041d-7b8f-a5c0-cef761a8f30c.gif)

次回はvue CLIでCRUDまでやります。