Vue.js入門 2章 Vue.jsの入門（ライフサイクルフック／メソッド）

前 [Vue.js入門 2章 Vue.jsの入門（ディレクティブ）](https://qiita.com/tseno/items/ccb0b99edbc2c1d136dc)
次 [Vue.js入門 3章 コンポーネントの基礎（コンポーネントとは何か／Vueコンポーネントの定義）](https://qiita.com/tseno/items/f3a7ef56c37e45a90b99)

# ライフサイクルフック

## ライフサイクルフック一覧とフロー

|フックの名前|フックが呼ばれるタイミング|
|:--|:--|
|beforeCreate|インスタンスが生成され、データが初期化される前|
|created|インスタンスが生成され、データが初期化された後|
|beforeMount|インスタンスがDOM要素にマウントされる前|
|mounted|インスタンスがDOM要素にマウントされた後|
|beforeUpdate|データが変更され、DOMに適用される前|
|updated|データが変更され、DOMに適用された後|
|beforeDestroy|Vueインスタンスが破棄される前|
|destroyed|Vueインスタンスが破棄された後|

## createdフック

- この段階ではまだDOM要素はインスタンスに紐づいていないので、DOM要素は取得できない
- Vuexを導入していないアプリでWeb APIと通信してデータに関する処理を開始したり、setInterval、setTimeoutで、処理を開始するポイントとして利用される。

## mountedフック

- DOM要素が紐づいた後に呼ばれ、DOM APIが利用できるようになる。DOM操作やイベントリスナーの登録が必要な場合に使われる。

## beforeDestroyフック

- インスタンスが破棄される前に呼ばれる。イベントリスナーの破棄、タイマー処理のクリアといった、後始末をここで行う。

```js
  var vm = new Vue({
    el: '#app',
    data: function () {
      return {
        count: 0,
        timerId: null
      }
    },
    created: function () {
      console.log('created')
      var that = this
      // データに参照できる
      console.log(this.count)
      // DOM 要素が紐付いていないので undefined
      console.log(this.$el)
      // タイマー処理を開始する
      this.timerId = setInterval(function () {
        that.count += 1
      }, 1000)
    },
    mounted: function () {
      console.log('mounted')
      // DOM 要素が紐付いている
      console.log(this.$el)
    },
    beforeDestroy: function () {
      console.log('beforeDestroy')
      // タイマーの後始末をおこなう
      clearInterval(this.timerId)
    }
  })
  window.vm = vm
```

- 実行すると呼び出しされていることがわかる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/88686/1930485f-4cf3-3101-964b-137699fff371.png)

# メソッド

- methodsは以下のように定義する。データの変更や、サーバーにHTTPリクエストを送る際に使われる。

```js
methods: {
  メソッド名: function() {
    // 処理
  }
}
```

- メソッドの呼び出し例。`$event`という変数を参照することができる。`doBuy($event)`と書いても可能。

```html
<button v-bind:disabled="!canBuy" v-on:click="doBuy">購入</button>
```

## イベントオブジェクト

- v-onディレクティブの属性値にメソッドを指定した場合は、引数にはデフォルトでイベントオブジェクトが渡される。

```js
methods: {
  メソッド名: function(event) {
    // 引数eventはイベントオブジェクト
  }
}
```

- 算出プロパティとメソッドの違いは、算出プロパティはキャッシュ機構があるということ。依存しているデータが変更されない限り、算出プロパティはキャッシュ値を使う。キャッシュされた値を使いたくない場合は、メソッドを使う。

## サンプルでのメソッドの呼び出し

- 購入ボタンを設置する。`<button v-bind:disabled="!canBuy" v-on:click="doBuy">購入</button>`
- doBuyメソッドを用意して、購入ボタンが押されたらdoBuyメソッドを呼び出し、alertを表示した後、数量を0に変更する。

```html
<script src="https://unpkg.com/vue@2.5.17"></script>
<div id="app">
  <ul>
    <li v-for="item in items" v-bind:key="item.name">
      {{ item.name }}の個数: <input type="number" v-model="item.quantity" min="0">
    </li>
  </ul>
  <hr>
  <div v-bind:style="errorMessageStyle">
    <ul>
      <li v-for="item in items" v-bind:key="item.name">
        {{ item.name }}: {{ item.price }} x {{ item.quantity }} = {{ item.price * item.quantity | numberWithDelimiter }}円
      </li>
    </ul>
    <p>{{ items[0].name }}: {{ items[0].price }} x {{ items[0].quantity }}</p>
    <p>小計: {{ totalPrice | numberWithDelimiter }}円</p>
    <p>合計(税込): {{ totalPriceWithTax | numberWithDelimiter }}円</p>
    <p v-show="!canBuy">
      {{ 1000 | numberWithDelimiter }}円以上からご購入いただけます
    </p>
    <!-- ボタンが押されたら、メソッドを呼び出す -->
    <button v-bind:disabled="!canBuy" v-on:click="doBuy">購入</button>
  </div>
</div>
```

```js
var items = [
  {
    name: '鉛筆',
    price: 300,
    quantity: 0
  },
  {
    name: 'ノート',
    price: 400,
    quantity: 0
  },
  {
    name: '消しゴム',
    price: 500,
    quantity: 0
  }
]
var vm = new Vue({
  el: '#app',
  data: {
    items: items
  },
  filters: {
    numberWithDelimiter: function (value) {
      if (!value) {
        return '0'
      }
      return value.toString().replace(/(\d)(?=(\d{3})+$)/g, '$1,')
    }
  },
  methods: {
    doBuy: function () {
      // 本来はここで、サーバーと通信をおこなう
      alert(this.totalPriceWithTax + '円のお買い上げ！')
      this.items.forEach(function (item) {
        item.quantity = 0
      })
    }
  },
  computed: {
    totalPrice: function () {
      return this.items.reduce(function (sum, item) {
        return sum + (item.price * item.quantity)
      }, 0)
    },
    totalPriceWithTax: function () {
      return Math.floor(this.totalPrice * 1.08)
    },
    canBuy: function () {
      return this.totalPrice >= 1000
    },
    errorMessageStyle: function () {
      // canBuyが偽の時に赤く表示する
      return {
        border: this.canBuy ? '' : '1px solid red',
        color: this.canBuy ? '' : 'red'
      }
    }
  }
})
window.vm = vm
```

- 数量を増やして、1000円以上になると購入ボタンが押せるようになる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/88686/3e98c1d6-0199-d609-4138-4009f385fe0a.png)

- 購入ボタンを押すと、ダイアログが表示される。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/88686/fb0cd108-5011-b6e0-e342-33afa915440f.png)

- 数量が0に戻り、再び購入ボタンが押せなくなる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/88686/f855ee1c-eced-dd9a-17a7-2097ba427ca5.png)

- まとめ
    - ライフサイクルフックは、初期設定や後始末をすることができる。
    - メソッドは、処理をまとめたり共通化することができる。イベント処理を行ったりサーバーとの通信などに使われる。$eventオブジェクトを取得できる。算出プロパティはキャッシュがあるが、メソッドはない。


参考
[Vue.js入門 基礎から実践アプリケーション開発まで](https://www.amazon.co.jp/dp/B07J6FP6NQ/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)