Vue で配列を使った算出プロパティの値が変わらないとき

1回ハマったら体が覚えて、次回から気を付けるようになるのだけど、記事にしておく。

例えば、以下のように配列をスタックとして使い、トップを算出プロパティで定義したとき。1秒後にトップの id が 100 になると思いきやそうはならない。Vue は push, pop, splice といった操作のメソッドをラップして、配列の変更を検知しているので、配列の要素へ代入しても配列の変更とはみなされない。

new Vue({
   data: {
      items: []
   },
   mounted() {
       this.items.push({id: 1});
       this.items.push({id: 2});
       this.items.push({id: 3});
       setTimeout(() => {
           this.items[this.items.length - 1] = {id: 100};
       }, 1000);
   },
   computed: {
      top() {
          if (this.items.length === 0) {
              return null;
          }
          return this.items[this.items.length - 1];
      }
   }
});

これを意図通りに動かすには setTimeout のコールバックの処理を次のように splice メソッドを使って変更するように書き換える。

this.items.splice(this.items.length - 1, 1, {id: 100});