【Vue.js】配列を更新しても反映されない(表示が変わらない)場合の対処法

2021年3月15日

手っ取り早くこのページのサンプルコードを検証するには、下記のvueライブラリを事前に読み込んでおいてください。

Vue.jsで配列を直接代入しても、結果が更新されない(リアクティブにならない)

Vue.jsは、配列変数を直接代入して中身を書き換えても、結果は反映されません。

以下のサンプルは、キー1(値にTwoが入っている)の値を書き換えていますが、リストが更新されていないのが分かります。

出力結果を実際に触ってみて確認してみてください。

サンプルコード
<div id="app-1">
    <ul>
        <li v-for="(value, key) in aryHoge">{{ value }}</li>
    </ul>    
    <input type="button" value="Twoを二に変更" @click="aryHoge[1] = '二'" />
</div>

<script>
new Vue({
    el: '#app-1',
    data: {
        aryHoge : ['One', 'Two', 'Three'],
    }
});
</script>
  • {{ value }}

何故変わらないかというと、Vueは配列の変更を検知するメソッドが決まっているからです。

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

https://jp.vuejs.org/v2/guide/list.html

これらの関数以外、今回でいえば直接代入をしても、配列の画面表示は変わりません。(変数はもちろん書き換わっています)

対処法

変更後、splice()を行う

値の代入後、splice()やsplice(0)などと入力し、そのメソッドをただの表示更新用として使うことで一応リアクティブに更新できます。

サンプルコード
<div id="app-2">
    <ul>
        <li v-for="(value, key) in aryHoge">{{ value }}</li>
    </ul>    
    <input type="button" value="Twoを二に変更" @click="aryHoge[1] = '二'; aryHoge.splice();" />
</div>

<script>
new Vue({
    el: '#app-2',
    data: {
        aryHoge : ['One', 'Two', 'Three'],
    }
});
</script>
  • {{ value }}

ただし、あまり直感的ではない記述ですね。

$set()を使う

Vueは配列の値の更新用の関数が用意されています。

$set(配列, キー, 値)と入力し、代入したいキーにその値を入れることでリアクティブに更新されます。

サンプルコード
<div id="app-3">
    <ul>
        <li v-for="(value, key) in aryHoge">{{ value }}</li>
    </ul>    
    <input type="button" value="Twoを二に変更" @click="$set(aryHoge, 1, '二');" />
</div>

<script>
new Vue({
    el: '#app-3',
    data: {
        aryHoge : ['One', 'Two', 'Three'],
    }
});
</script>
  • {{ value }}

methodsで更新をかける場合はthisを先頭に付ける必要があるので注意です。

サンプルコード
<div id="app-4">
    <ul>
        <li v-for="(value, key) in aryHoge">{{ value }}</li>
    </ul>    
    <input type="button" value="Twoを二に変更" @click="changeTwo();" />
</div>

<script>
new Vue({
    el: '#app-4',
    data: {
        aryHoge : ['One', 'Two', 'Three'],
    },
    methods : {
        changeTwo : function(){
            this.$set(this.aryHoge, 1, '二');
        }
    }
});
</script>
  • {{ value }}

オブジェクトはリアクティブに更新される

ちなみにですが、配列ではなくオブジェクト形式の場合、リアクティブに更新されるので、この違いも知っておくと間違いに気づきやすいです。

サンプルコード
<div id="app-5">
    <ul>
        <li v-for="(value, key) in aryHoge">{{ value }}</li>
    </ul>
    <input type="button" value="Twoを二に変更" @click="aryHoge[2] = '二'" />
</div>

<script>
new Vue({
    el: '#app-5',
    data: {
        aryHoge : {1 : 'One', 2 : 'Two', 3 : 'Three'},
    }
});
</script>
  • {{ value }}

以上、配列を更新しても反映されない(表示が変わらない)場合の対処法、でした。

Vue.js