Ne:Code道場~computed②の巻~


	Ne:Code道場~computed②の巻~

プログラミング学習で、漫画など視覚的なものと併用すると楽しく継続的に学んでゆける人も多いと思います。そこでこの連載では、猫の漫画を交えつつ、JavaScriptのフレームワーク、Vue.jsのcomputedにおける学習ポイントについて紹介します。

目次
  1. はじめに
  2. computedをv-modelに用いることができるのニャ?
  3. computedで定義したものをv-modelに用いる場合はどうするニャ?
  4. 最後に

はじめに

image この記事ではVue.jsのcomputedについて、2回目ということでバインドする際の書き方を取り上げつつ、躓きポイント を補足しています。 各節ごとに、Ne:Code道場(猫de道場)の弟子猫がポイントをまとめ、最後に師匠猫がそれらを総括して3ポイントでまとめています。 それらのポイントを中心に、Vue.jsのcomputedについて理解を深めてゆきましょう。
(いままでの記事もそうですが、Vue.jsはバージョンは2を用いています。サンプルコードで「vue@2.6.0」という部分でその指定を行っています。Vue.jsの最後で今まで取り上げたものとバージョン3での比較をまとめたいと思っています)

computedをv-modelに用いることができるのニャ?

前回の記事では、Vue.jsのcomputedの1つ目の記事として、値をそのままではなく、リアルタイムに加工した結果を用いる書き方を確認しましたね。computedの中で定義しているものは、returnで値を返しているメソッドでした。なので、v-modelでバインドしたいと思っても、値を返す(return)ことはできても、入力された値を設定することはできません。
まず、そのNGなパターンからみてゆきます。
最初にJavaScriptからです。

new Vue({
  el: "#app",
  data: {
    // 値段を管理する用の変数ニャ
    price: 0,
  },
  computed: {
    priceDisplay() {
      // 前回学んだのと同じcomputedの書き方ニャ
      // returnだけが書いてあるニャ!
      return `${this.price}円ニャ`;
    }
  }
});

シンプルな形でまとめてみました。必要最低限のdataとcomputedのみを記載しています。computedは、前回同様、dataのprice変数を加工して返すだけというものになっているのを確認できるでしょう。
次にHTML側を見てゆきます。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>お試しHTMLニャ</title>
</head>
<body>
  <div id="app">
    <!-- ニャ!computedのpriceDisplayがv-modelに設定されているニャ -->
    <input type="text" v-model="priceDisplay">
    <!-- ニャ~。ここは動作確認用ということで記載されているニャ -->
    <!-- 以前v-modelを学んだ際には、入力コントロールの値を変えたら、表示用も連動して変わっているのを確認したニャ -->
    {{ priceDisplay }}
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
  <script src="script.js"></script>
</body>
</html>

computedで定義したpriceDisplayがv-modelに設定されているのを確認できますね。実行してみますと、初期状態では、入力エリアも、出力エリアも「0円ニャ」と表示されています。ここまでの動作は問題ありませんが、入力エリアの値を変えても、連動して出力エリアは変わりません。現在のcomputedでの定義の仕方が、returnで値を取得するだけの、読み取り専用の定義になっているからなのですね。
でも、computedに定義したものをv-modelに用いることができる書き方があるのです。今回はその書き方を見てゆきましょう。
image

computedで定義したものをv-modelに用いる場合はどうするニャ?

まずは具体的にどういう書き方になるのかをみてゆきましょう。その後、書いている内容について補足してゆきます。こちらの内容の説明用に、サンプルコードの構成から変更しています。あくまで説明用に設けたコードになりますので、学習用のコードとして、猫弟子の驚きコメントとあわせてご確認ください。

new Vue({
  el: "#app",
  data: {
    // dataに新しく入れ子(nest)のオブジェクトが定義されているニャ
    nestObject: {
      // そのオブジェクトの子供(child)として、まんまな名前のプロパティが定義されているニャ
      child: true
    },
  },
  computed: {
    // ニャ?!今までcomputedには、メソッドっぽくかいていたけれど、ここでは上のnestObjectみたいなオブジェクト定義になっているニャ!
    child: {
      // ニャ??!get、setで定義されているニャ?
      // get → 取得するっていうイメージがあるニャ!
      get() {
        // 入れ子オブジェクトのchildプロパティをreturnしているニャ!
        // returnを使っているから、戻り値がある書き方ニャ~
        return this.nestObject.child;
      },      
      // set → 設定するっていうイメージがあるニャ!
      // getには書いていなかった、引数が書いてあるニャ~
      set(value) {
        // その引数を入れ子オブジェクトのchildプロパティに設定しているニャ!
        this.nestObject.child = value;
      }
    }
  }
});

computedの部分が書き方が大きく変わっていますね。v-modelに用いる場合は、値を取得するだけではなく、設定する必要があります。なので、computedの定義時にも、getとsetが用いられているのですね。これはそれぞれ、getter関数、setter関数と呼ばれるものです。それぞれの仔細は一旦はこの記事では割愛しますが、値を取得・設定する際に用いられる関数で、JavaScriptに限らず、プログラミングをしていると良くお目にかかる名前の関数だとだけ抑えておきましょう。
上記にも書きましたが、こちらのサンプルコードはあくまで学習用で書いています。元のサンプルコードのpriceでgetter関数、setter関数を書くとしたら、以下のようなシンプルな仕組みになってしまうため、どういう旨味がありえるのかを少しでも体感してもらいたいと思いサンプルコードを記載しました。

    priceBind: {
      get() {
        // dataのpriceをただ返しているだけニャ
        // 元のサンプルコードでは末尾に文字をつけていたけれど、説明のために端折っているニャ
        return this.price;
      },
      set(value) {
        // ただ引数をdataのpriceに設定しているだけニャ
        this.price = value;
      }
    }

上記は参考としてのせましたが、同じくgetter関数とsetter関数を利用しているという部分には類似性を確認できますよね。もしもこのpriceの例でHTML側でv-modelに用いる際には、「v-model="price"」で書いても良いですし、「v-model="priceBind"」でも同様に動作します。(computedにおける、getter関数・setter関数の学習用コードなので、本来なら普通に「v-model="price"」の書き方をします)
では改めて、入れ子オブジェクトを用いている例でのHTML側の記載を見てみましょう。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>お試しHTMLニャ</title>
</head>
<body>
  <div id="app">
    <!-- computedに定義しているchild、今回はしっかりバインドできているニャ -->
    <input type="checkbox" v-model="child">
    <!-- 参考までに、↓の書き方でももちろんOKニャ!上の書き方だと、より短くなってシンプルな記載であるというのが確認できるニャ~ -->
    <!-- <input type="checkbox" v-model="nestObject.child"> -->
    <!-- チェックした結果の動きを確認するように記載しているニャ -->
    {{ nestObject }}
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
  <script src="script.js"></script>
</body>
</html>

computedで書いてあるものでも、ちゃんと取得・設定のgetter関数・setter関数を設けてあげる書き方をすれば、dataに定義しているもののようにv-modelでバインド利用することが可能だというのを確認できましたね。
コメントでも書いてあるように、入れ子になっているオブジェクトのプロパティをそのままバインドしても同じ様に動作します。今回は入れ子1つですが、この入れ子が多くなったりすると、computedでそのまま取得できている書き方の方がとてもシンプルで見やすいと確認できますね。
「computedは取得用」と覚えておくよりは、「computedでもバインド用の定義を書く方法がある」と覚えておくほうが引き出しが増え、活用できる幅がぐっと広がると思います。
image

Webサイト担当者としてのスキルが身に付く

無料カウンセリングはこちら

最後に

Vue.jsのcomputedについて、猫弟子がいくつか上げたポイントを、猫師匠が厳選3ポイントでまとめたのがこちらです。

  1. computedに定義したものは、取得のみの書き方をしていたらv-modelにバインドしても期待する動作にはならないニャ
    1. 取得のみの場合は、値がreturnで返されるだけニャので、v-modelのバインドで入力された値を保持しておくことができないニャ
  2. getter関数とsetter関数込でcomputedに定義すれば、v-modelにバインド可能になるニャ
    1. 値を取得する際にはgetter関数、設定する際にはsetter関数が内部的に呼ばれることで、v-modelのバインドが動作するようになるニャ
  3. computedの利用できる範囲を知っていると、その引き出しを活用してゆくことができるニャ
    1. 使い方はまだイメージできなくてもOKニャ。書き方を知っておくと、そういう書き方を見たときとかの「?」感が下がり、とっつきやすくなるニャ~
    2. お試しの例として、入れ子になっているオブジェクトをシンプルにバインドさせる例を取り上げていたニャ。サンプルでは入れ子階層も1つだけれど、これがもっと深い階層になったらと想像してみるのもありニャ

Vue.jsの10個目の記事として、Vue.jsのcomputedについて学びました。
見た目のフレームワークとしてVue.jsを学ぶことで、JavaScriptとしてできることがぐっと高まってゆくと思います。
するとコードへの理解も深まり、プログラミングが更に楽しくなってくるでしょう。
Vue.js導入に関連する知識をしっかり身につけつつ、今後の学習に繋げてゆきましょう。
image


小泉七菜
この記事を書いた人
小泉七菜
まずは7日間お試し!人気プログラミング講座を無料公開中
オンライン・プログラミングレッスンNo.1のCodeCamp