Vue.js始めるおれおれアドベントカレンダー2016 – 6日目
Vueでは data, methods の他に、両者の特性を併せ持った computed というものを指定することができます。これすげーんでお見知りおきください。
- 公式ドキュメント: 算出プロパティとウォッチャ – vue.js
- デモ
- コード
data と methods
この二つはまあ普通なんですが、 data がデータ、 methods がメソッドです。そのまんまだ。
イニシャルを表示する例
JS側で getInitial() というメソッドを実装して、HTML側で {{getInitial()}} と書いて呼び出しています。
<div id="app">
<p>
<label>
First Name:
<input v-model="firstName" type="text" />
</label>
<br />
<label>
Last Name:
<input v-model="lastName" type="text" />
</label>
</p>
<h1>Hello {{getInitial()}}!</h1>
</div>
var app = new Vue({
el: '#app',
data: {
firstName: 'ginpei',
lastName: 'takanashi',
},
methods: {
getInitial: function() {
var firstFirstNameLetter = this.getInitialOf(this.firstName);
var firstLastNameLetter = this.getInitialOf(this.lastName);
var initial = firstFirstNameLetter + '.' + firstLastNameLetter + '.';
return initial;
},
/**
* @param {string} name
* @returns {string}
* @example
* this.getInitialOf("alice"); // => "A"
*/
getInitialOf: function(name) {
return name.charAt(0).toUpperCase();
},
},
});

まあ普通ですね。
computed
computed を使うと、先ほどの例がこう書けます。(だいたい一緒なので違う部分だけ。)
<h1>Hello {{initial}}!</h1>
computed: {
initial: function() {
var firstFirstNameLetter = this.getInitialOf(this.firstName);
var firstLastNameLetter = this.getInitialOf(this.lastName);
var initial = firstFirstNameLetter + '.' + firstLastNameLetter + '.';
return initial;
},
},
HTML側では data のように名前を書くだけ、JS側では methods のように関数を実装しています。
何かをあれこれ処理しているのではなくて、ここでは(処理した)結果をただ表示するぞ、というのが分かりやすいかと思います。え、そうでもない?
キャッシュ
メソッドとの最大の違いは、結果がキャッシュされ毎回実行されないという点です。
ドキュメントから引用します。( message が data に格納されており、それを順序反転する処理 reversedMessage が computed で定義されている文脈です。)
算出プロパティの代わりに、同じような関数をメソッドとして定義することも可能です。最終的には、2つのアプローチは完全に同じ結果になります。しかしながら、算出プロパティは依存関係にもとづきキャッシュされるという違いがあります。算出プロパティは、それが依存するものが更新されたときにだけ再評価されます。これはつまり、
messageが変わらない限りは、reversedMessageに何度アクセスしても、関数を再び実行することなく以前計算された結果を即時に返すということです。
参照している値を自動的に監視して、最低限の実行で処理してくれるそうです。すんげー。
注意点
逆に、 data の値を参照していない場合、例えば先のドキュメントでは Date.now() が使われていましたこういう場合には、キャッシュされた値は更新されなくなってしまうようです。
メソッドはあまり使わない?
というわけで画面に出力する計算は computed でやるのが良さそうです。
Date.now() みたいにVue外から情報を得る場合は、取得した結果を data に入れてそれを computed で出力するーみたいな感じでしょうか。コンポーネントなら porps 経由で。
するとメソッドを使う場面は、今回みたいにDRY的に単純に処理をまとめるのと、イベントハンドラを定義するのくらいでしょうか。
ユーザー一覧の各項目で情報を加工する場合はどうだろ。 doSomething(list[i]) みたいなのが必要? いやコンポーネントに分けて、子の方で porps で受けた値を computed でやれば良さそう。
というのを作ってみた:

うーんこんな感じなんだろうか。日時情報の扱いはもっと上手にやれそうな気がする?