[Vue.js]算出プロパティとメソッドの違い

# 算出プロパティとメソッドの違い
Vue.jsの初学者が必ず？？？となるポイントとして`算出プロパティとメソッドの違い`があるかと思いますのでその違いについてまとめます。

## 今回の主役
### computed
算出プロパティは関数で算出したデータを返すことができるプロパティのことです。要はgetterの役割だと思ってもらえれば良いかと思います。

```html
<div id="app">
  {{ fullName }}
</div>
```
```javascript
var app = new Vue({
  el: '#app',
  data: {
    firstName: 'Sato',
    lastName: 'Taro'
  },
  computed: {
    fullName: function() {
      return this.firstName + ' ' + this.lastName
    }
  } 
})
```

### methods
先ほどの例だと、メソッドを使っても同じことが実現できます。

```html
<div id="app">
  {{ fullName }}
  {{ fullNameMethod() }}
</div>
```
```javascript
var app = new Vue({
  el: '#app',
  data: {
    firstName: 'Sato',
    lastName: 'Taro'
  },
  computed: {
    fullName: function() {
      return this.firstName + ' ' + this.lastName
    }
  },
  methods: {
    fullNameMethod: function() {
      return this.firstName + ' ' + this.lastName
    }
  } 
})
```

# computed vs methods
##算出プロパティとメソッドの違い
||computed(算出プロパティ)|methods(メソッド)|
|:--|:--|:--|
|記法|（）不要|()必要|
|用途|getter(setter)|getter, setter|
|キャッシュ|__される__|されない|

## 記法の違い
__computed__
「()」は不要 ＝ 引数を伴う処理ができない

__methods__
「()」が必要 ＝ 引数を使った処理が可能

## 用途の違い
__computed__
データの加工を伴った取得(getter)　※１

__methods__
データの取得に限らず、操作やデータの更新等様々な処理に使用

__(※1) 算出 Setter 関数__
算出プロパティはデフォルトはgetterのみですが、セッターとしても使用することはできます。

```javascript
// ...
computed: {
  fullName: {
    // getter 関数
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter 関数
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}
// ...
```
[参考：公式 Vue,js](https://jp.vuejs.org/v2/guide/computed.html#%E7%AE%97%E5%87%BA-Setter-%E9%96%A2%E6%95%B0)

## 算出プロパティのキャッシュ
ここからがこの記事のメインとなります。
算出プロパティとメソッドの使い分け方の考えとして、キャッシュの有無があります。

### キャッシュ動作の確認
Mathのランダム関数を使ってキャッシュの違いを説明します。

```html
<div id="app">
  メソッド
  <ol>
    <li> {{ getDate() }}</li>
    <li> {{ getDate() }}</li>
    <li> {{ getDate() }}</li>  
  </ol>
  算出プロパティ
  <ol>
    <li>{{ date }}</li>
    <li>{{ date }}</li>
    <li>{{ date }}</li>
  </ol>
</div>
```
```javascript
var app = new Vue({
  el: "#app",
  computed: {
    date: function () {
    　console.log("computed");
      return Math.random();
    }
  },
  methods: {
    getDate: function () {
    　console.log("methods");
      return Math.random();
    }
  }
});
```
```:出力結果
メソッド
0.523744236259859
0.29754866940841374
0.3024997149055251

算出プロパティ
0.19494595412700444
0.19494595412700444
0.1949459541270044
```
このように同じMath.random()を使っても、算出プロパティは全て同じ値に対してメソッドは全てバラバラの値になりました。

![スクリーンショット 2019-08-11 14.42.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234184/327678dc-f9a2-8b26-b7d2-8d41f9ef86c7.png)
また算出プロパティは描画は3度していますが、コンソールログには1度しかログが出ていません。

### computedはプロパティに依存しない場合は1度しか実行されない
methodsは再描画が起きると常に実行されるのに対して、算出プロパティの処理はプロパティ(this.~)に変化があった場合のみ、再実行されるという性質があります。
要は毎回同じ結果になるなら、1回処理したらいいだろうといった考えです。

これを公式ドキュメントの言葉を使うと`算出プロパティはリアクティブな依存関係にもとづきキャッシュされる`と表現できます。

#### リアクティブデータ
Vueクラスのdataオプションに設定されているデータを、Vue.jsの世界ではリアクティブデータと呼びます。
データの変化を検知して自動的に反映させることができるからのようです。

```javascript:リアクティブデータの依存関係がある
  data: {
    sum: 1,
  },
  computed: {
    date: function () {
    　console.log("computed");
      return Math.random() + this.sum; // sumが更新されたら再実行される
    }
  }
```
```javascript:リアクティブデータの依存関係がない
  computed: {
    date: function () {
      return Math.random(); // キャッシュされ2度と実行されない
    }
  }
```
キャッシュ機能はこの程度の処理であれば大して変わりませんが、大量の配列データをループして回すコストの高い処理があった場合にパフォーマンスに大きな違いが出ます。

## まとめ： 算出プロパティとメソッドの使い分け
__算出プロパティ__
　・ 引数が不要な単純な処理の場合(用途がわかりやすいため)
　・ キャッシュが効果的な場面で、処理を高速化させたい場合

__メソッド__
　・ 引数が必要となるような処理
　・ あえてキャッシュさせたくない場合、値を常に更新したい場合(先ほどのランダム関数を使った処理など)
　・ キャッシュの話がよくわからない場合(よくわからずに算出プロパティを使うと思わぬバグに繋がります)

# 最後に一言
算出プロパティとメソッドの違いは`キャッシュを意識しろ`ってことですね！

# 参考
[Vue.js 公式ドキュメント](https://012-jp.vuejs.org/)
[これからはじめるVue.js実践入門](https://www.amazon.co.jp/dp/B07WVXRNH3/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)