親バカエンジニアのナレッジ帳

webのエンジニアをやっており、日頃の開発で詰まったことや書き残しておきたいことを載せています。育児のイロハという育児サイト(https://ikujip.jp)の開発も行っているため、その開発で使用されている技術についても掲載しています。

Vue.jsのdataプロパティでオブジェクトの変更は$setで置き換えろ!

dataプロパティでオブジェクトの定義

Vue.jsでインスタンスを生成した際、dataオブジェクトに変数を定義した場合のリアクティブな動作についてはご存知だと思いますが、テンプレート内でdataオブジェクトに定義した変数を使用していた場合、変数の中身が変更されるとリアクティブに変更されます。

リアクティブについて詳細に述べるのは別な機会にするとして、簡単に言えば変数が変更されると、それに応じてテンプレート内で使用されている箇所も同時に変更され、変更後の値に応じた振る舞いをします。
単なる文字列(String)や数値(Integer)、真偽値(Boolean)の場合だけではなく、配列(Array)やオブジェクト(Object)の場合も同様です。

「dataプロパティに定義されているオブジェクトの変更 → テンプレートでの振る舞いの変更」と繋がるはずですが、オブジェクトと配列の場合は変更の仕方に注意が必要です。
ここではdataプロパティで定義されたオブジェクトの値を変更する方法について述べます。

変更する場合は$setで置き換え

例えばdataプロパティで以下のような定義をした場合、

export default {
  data () {
    return {
      testObject: {'name': 'test1-Name': 'value': 'test1-Value'}
    }
  }
}

valueの値のみ「test2-Value」と変更したい場合、いつもの流れだと以下のようにしたくありませんか?

this.testObject.value = 'test2-Value'

残念ながらこの変更方法はVue.jsではやらない方が良いです。
変数の値自体は当然変更できるのですが、リアクティブではなくなるのです。
つまり、オブジェクトの変更により、テンプレート側でなんらかの動作の変化が起きるようにプログラムされている場合、オブジェクトを変更してもテンプレートには何ら変化は起きないのです。

元々Javascriptを長く使っていた人ほど、Vueを使い始めた頃はかなりハマるのではないでしょうか。
Vue.jsでdataプロパティで定義したオブジェクトを変更する場合は以下のように$setを使いましょう。

this.$set(this.testObject, 'value', 'test2-Value')

使い慣れない関数だと思いますが、これで変更するようにすればリアクティブに変更されます。

配列中のオブジェクトはループなどで同様に変更可能

以下のように、配列の中でオブジェクトの定義をしている場合も同様に$setを使えば解決です。

export default {
  data () {
    return {
      testObject = [
        {'name': 'test1-Name': 'value': 'test1-Value'},
        {'name': 'test2-Name': 'value': 'test2-Value'}
      ]
    }
  }
}

配列の場合は、配列中のどのキーのオブジェクトを変更すれば良いのか指定する必要があるので、そのような場合はループを使えば変更が可能です。

例1) 配列の2番目(インデックスのキーが1)の場合にvalueを変更する場合

this.testObject.forEach((object, index) => {
  if (index === 1) {
    this.$set(this.testObject[index], 'value', 'test2-Value')
  }
})

例2) nameが「test2-Name」の場合にvalueを変更する場合

this.testObject.forEach((object, index) => {
  if (object.name === 'test2-Name') {
    this.$set(this.testObject[index], 'value', 'test2-Value')
  }
})

こんな感じでオブジェクトでもリアクティブな動作が可能となります。

今回はオブジェクトのリアクティブな動作について記載しましたが、配列についても以下に記していますのでぜひとも参考にしてください。

ti-tomo-knowledge.hatenablog.com

基礎から学ぶ Vue.js

基礎から学ぶ Vue.js

速習Vue.js 速習シリーズ

速習Vue.js 速習シリーズ

Vue.jsとFirebaseで作るミニWebサービス (技術書典シリーズ(NextPublishing))

Vue.jsとFirebaseで作るミニWebサービス (技術書典シリーズ(NextPublishing))