#初めに
JavaScriptを学び終え、Vueを学んでいると最初computedとmethods違いってなに?
という壁にあたることがあるあるだと思います。
まず一番の違いとして出てくるワードがキャッシュかなと思います。
UIのデータ定義で使うdataプロパティについての話やVuexの話も含めて書いていきます。
#computed(算出プロパティ)
算出プロパティのキャッシュなんているワードがでてきますが、イメージ的には一度計算してくれて、再計算までデータの状態を保持してくれる。
これを利用して、コンポーネントで使うデータ定義をdataで書かずcomputedに持たせてあげる方法もあります。
※全く計算を行ってないデータをdataで定義せず、computedにデータを持たせて表示できますが、可読性が下がるのでやらないでください!
<template>
<div>
<p>{{apple.price}}</p>
</div>
</template>
<script>
export default {
data(){
return{
apple: {
price:100,
number:3,
}
}
}
};
</script>
可読性が下がるアンチパターン↓
<template>
<div>
<p>{{apple}}</p>
</div>
</template>
<script>
export default {
computed:{
apple:function(){
return 100
}
}
};
</script>
detaで定義してあげたデータをthisを使ってcomputedから参照して、computedで計算してみましょう!
<template>
<div>
<p>{{total}}</p>
</div>
</template>
<script>
export default {
data(){
return{
apple: {
price:100,
number:3,
}
}
},
computed:{
total:function(){
return this.apple.price * this.apple.number //300
}
}
};
</script>
計算処理を行った上でテンプレートに値を表示してますよね!そしてりんごの値段(apple.price)と個数(apple.number)が変化してお会計(total)が変化するまでキャッシュとしてデータの状態は保持してくれます!
※methodsはキャッシュをもってくれないので、methodsが呼ばれるたびに再計算されています。
##computedが再計算してれくない!?
computedはキャッシュしている依存するデータに対して変更があった時に再計算が必要になり、再計算をしてDOM側に反映(リアクティブ)してくれるのですが、再計算してくれない時があります。
その原因の一つとしてVueインスタンス内のデータではない、現在日時(Date.now())やDOMの状態といったVueインスタンス外とのやりとりはその値の変更を検知できないので、再計算が行われません。
##computed × Vuex(状態管理してくれるモジュール)
コンポーネントをデータをまたぐときに親から子どもに渡すときはpropsを使うと思いますが、コンポーネントをデータをまたぎまくって頭がスパゲティ状態になり、どんだけコンポーネントまたげばデータ渡せるんだよ。もう無理だ。なんて時にVuexを使うことになるんですが、
その時にもcomputedは活躍してくれます。stateやgetterからstoreを参照するときにcomputedから参照できますね!
コンポーネント内だけで使うデータ定義をdetaに書き、storeを参照する場合はcomputedに書いてあげれば、より綺麗なコードがかけると思います!
※Vueインスタンス内を一部抜粋しました
data() {
return {
apple: "りんご",
orange: "みかん",
};
},
computed: {
Supermarket() {
return this.$store.getters.Supermarket;
},
Convenience() {
return this.$store.state.Convenience;
},
},
#methods(メソッド)
データの変更やv-on ディレクティブを使ってクリック時などイベントが起きた時にセットで使われることが多いのですが、
DOMの状態などをテンプレートから引数としてmethodsに渡しやすいのが特徴ですね。
##引数
computedsに書いた関数にもテンプレートから引数を渡すことは可能ですが、methodsに書いた関数に渡すことをお勧めします。
まずはmethodsに書いた関数に渡す方法の紹介です
<template>
<div>
<button v-on:click="eat($event)">ボタン</button>
</div>
</template>
<script>
export default {
methods: {
eat: function(event) {
console.log(event.target); //<button>ボタン</button>
}
}
};
</script>
次にcomputedsに書いた関数に渡す方法の紹介です。
しかしなぜ引数を渡せているのか仕組みはわかりません。なんとなく書けちゃってます。ごめんなさい。
可読性が下がるであまり使わない方が良さげですね。
<template>
<div>
<button v-on:click="eat($event)">ボタン</button>
</div>
</template>
<script>
export default {
computed: {
eat: function() {
return function(event){
console.log(event.target); //<button>ボタン</button>
}
}
}
};
</script>
テンプレートから引数を渡せるとv-forの中に関数を書いとおくと、今何番目にいるかもわかって便利ですね!
#まとめ
computedは計算、再計算、キャッシュ
methodsはイベント、引数
イメージするとこんな感じでしょう!