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

webのエンジニアをやっており、日頃の開発で詰まったことや書き残しておきたいことを載せています。

Vue.jsのdataプロパティで配列の変更はspliceで置き換えろ!


dataプロパティで配列の定義

ti-tomo-knowledge.hatenablog.com

のページで、Vue.jsではdataプロパティの変更がリアクティブに変化すること、また、それを単なる変数ではなくオブジェクトでも実現させるための方法について説明しましたが、このページではdataプロパティで配列を定義した場合にリアクティブに動作させる方法を説明します。

オブジェクトに続いて、配列でも変更の仕方に注意が必要になるのです。

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

オブジェクトの変更で使用していた$setと同様、配列でもspliceという使い慣れない関数を使うことになります。
例えばdataプロパティで以下のような定義をした場合、

export default {
  data () {
    return {
      testArray: ['test1-Value', 'test2-Value', 'test3-Value']
    }
  }
}

配列の3番目(インデックスのキーが2)の値をvalueの値のみ「test5-Value」と変更したい場合、いつもの流れだと以下のようにしたくありませんか?

this.testArray[2] = 'test5-Value'

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

オブジェクトの変更同様に元々Javascriptや他の言語に慣れている人ほど、かなりハマりそうですね。
Vue.jsでdataプロパティで定義した配列を変更する場合は、以下のようにspliceを使いましょう。
引数が3つあってわかりづらいかもですが、以下で配列の3番目(インデックスのキーが2)を変更できるのです。

this.testArray.splice(2, 1, 'test5-Value')

配列の3番目(インデックスのキーが2)から数えて1つ目を置き換えという意味です。
使い慣れない関数だと思いますが、これで変更するようにすればリアクティブに変更されます。



削除する場合もsplice

Javascriptでは配列を削除する場合に、削除するキーによってはshift()やpop()を使ったりできますが、Vue.jsでは一律spliceを使いましょう。
例えば先ほどの配列で、配列の3番目(インデックスのキーが2)を削除したい場合、配列の末尾なので以下のようにpop()を使いたくなるでしょう。

this.testArray.pop()

でも、これではリアクティブに変更されないのです。
置き換えだけではなく、削除の場合にもspliceを使えるので、以下のようにしてください。

this.testArray.splice(2, 1)

配列の3番目(インデックスのキーが2)から数えて1つ目を削除するという意味です。


以下のようにすれば、配列の3番目(インデックスのキーが2)から数えて2つ目までを削除するという意味で、まとめて2つの項目を削除できます。

this.testArray.splice(2, 2)

末尾に追加する場合は従来通りpushを使え

dataプロパティの配列に新しい要素を追加する場合は、従来のJavascript同様にpush()を使えば大丈夫です。
以下のような配列が定義されている場合に「test3-Value」を追加したいとします。

export default {
  data () {
    return {
      testArray: ['test1-Value', 'test2-Value']
    }
  }
}

この場合は以下のようにしたくなるのものですが、これではリアクティブに変化しません。

this.testArray[2] = 'test3-Value'


以下のようにpushで追加すればリアクティブに動作します。

this.testArray.push('test3-Value')



多次元配列はループなどで同様に変更可能

以下のように、多次元配列の定義をしている場合も同様にspliceを使えば解決です。

export default {
  data () {
    return {
      testArray = [
        ['test1', 'test2'],
        ['test3', 'test4']
      ]
    }
  }
}

それぞれの配列の2番目(インデックスのキーが1)の値を変更する場合

this.testArray.forEach(array => {
  array.splice(1, 1, 'test10')
})

こんな感じで配列でもリアクティブな動作が可能となります。
慣れるまでは面倒ですが、慣れてしまえば問題ありません。



速習Vue.js 速習シリーズ

速習Vue.js 速習シリーズ

  • 作者:山田祥寛
  • 発売日: 2018/03/28
  • メディア: Kindle版
Vue.jsとFirebaseで作るミニWebサービス (技術書典シリーズ(NextPublishing))

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

  • 作者:渡邊 達明
  • 発売日: 2018/07/13
  • メディア: オンデマンド (ペーパーバック)