Help us understand the problem. What is going on with this article?

Vue.js 算出プロパティを活用すべきというお話

はじめに

私自身、あまり説明書を読まない派の人間です(子供の頃は熟読してたけどいつの間にか変わっていた)。
なにかしらの技術を新しく学ぶとなったときももちろん勉強のフェーズではドキュメント読んだり参考書読んだりするわけですが中々隅々まで目を通せていないことが多いです。これが原因でソースレビューで「これ使ったほうがいいよ」と便利・有用なモノを教えてもらうこともしばしば。

今回は私と似た性格の人・Vueをこれから学ぶよって方へ向けた、Vueの「算出プロパティ」について紹介します。

算出プロパティとは

あるデータに依存しているデータ(Aを元に生成されるBのような)がある場合、Vueでは何種類かの実装手段があります。
文章だと分かりづらいのでまずは例を・・・
入力値「苗字」と「名前」(上の説明でいうA)を元に、フルネーム(上の説明でいうB)を表示する処理を各手段ごとに書いてみました。
スクリーンショット 2018-12-21 16.38.57.png

↑こんな感じです。各ケース、入力値に応じてフルネームがリアルタイムで更新されます。

・テンプレートに直接書く方法

<div id="test">
  苗字<input v-model="lastName"><br>
  名前<input v-model="firstName">
  <p>Full Name: {{ lastName + ' ' + firstName }}</p>
</div>
var vm = new Vue({
  el: '#test',
  data: {
    lastName: '',
    firstName: '',
  }
})

この例の処理くらいだったらまだマシですが、基本的にテンプレートに処理は書きたくないですよね。

・処理をメソッドに切り出す方法

<div id="test">
  苗字<input v-model="lastName" v-on:keyup="updateName"><br>
  名前<input v-model="firstName" v-on:keyup="updateName">
  <p>Full Name: {{ fullName }}</p>
</div>
var vm = new Vue({
  el: '#test',
  data: {
    lastName: '',
    firstName: '',
    fullName: ''
  },
  methods: {
   updateName: function () {
      this.fullName = this.lastName + ' ' + this.firstName
    }
  }
})

無事にテンプレートから処理を切り出すことができました。
しかし、たったこれだけのことなのにテンプレート側がややごちゃごちゃしてしまいました。

・監視プロパティで実装する方法

<div id="test">
  苗字<input v-model="lastName"><br>
  名前<input v-model="firstName">
  <p>Full Name: {{ fullName }}</p>
</div>
var vm = new Vue({
  el: '#test',
  data: {
    lastName: '',
    firstName: '',
    fullName: ''
  },
  watch: {
    lastName: function (val) {
      this.fullName = this.lastName + ' ' + this.firstName
    },
    firstName: function (val) {
      this.fullName = this.lastName + ' ' + this.firstName
    }
  }
})

watchを利用してlastNameとfirstNameの更新を監視しており、更新があったらfullNameを再生成する動きです。methodsでの実装と比較するとテンプレート側はスマートになりますが、処理側が冗長になっています。

・算出プロパティ

<div id="test">
  苗字<input v-model="lastName"><br>
  名前<input v-model="firstName">
  <p>Full Name: {{ fullName }}</p>
</div>
var vm = new Vue({
  el: '#test',
  data: {
    lastName: '',
    firstName: ''
  },
  computed: {
   fullName: function () {
      return this.lastName + ' ' + this.firstName
    }
  }
})

いかがでしょうか。パッと見でもスマートになった感があると思います。
算出プロパティであるfullNameは、依存するデータ(lastName,firstName)に更新が入ったときのみ自動で処理が実行され、キャッシュされます
つまり、依存するデータに更新がない状態で再描画が走っても処理は実行されず、キャッシュから即時にデータを取り出します。この程度の処理であれば差を感じることはありませんが、Vue側で膨大な量のデータを加工しないといけないといったケースにおいてはマストで利用していきたい機能です。

デメリット

処理実行頻度の制御など、一部のケースにおいて算出プロパティでは実現できないものが存在します。(公式ドキュメントに例があるのでそちらを参照願います)
https://jp.vuejs.org/v2/guide/computed.html#%E3%82%A6%E3%82%A9%E3%83%83%E3%83%81%E3%83%A3

あとがき

先に述べましたが、実際算出プロパティを使わなくても実装上は困らないためドキュメントをあまり読まない人は知らずに実装進めちゃいそうだなと思い(自戒も込めて)紹介させていただきました。
可読性やパフォーマンス面等において利用できるならしたほうがいいケースがほとんど(できるのにあえてしないケースが思い浮かばない)ではないでしょうか。
ReluxにおいてVueを利用するかどうかはまだ検討中ですが、利用するときはまず「算出プロパティが適用できるか」から考え、それが難しかった場合に適宜ウォッチャ等で実装していくという進め方を心がけていこうと思います。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away