2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Vue.js】オブジェクトのプロパティを追加してもリアクティブに動作しなかった時の備忘録

Last updated at Posted at 2021-02-07

vue.jsでオブジェクトに新しくプロパティを追加してもリアクティブに動作しません。
未定義のプロパティをv-ifで参照させた時に、この事象に遭遇したため、調査してまとめました。


以下の3つのケースの変数を、v-ifに指定した場合の挙動について見ていきましょう。

  • プリミティブな変数
  • オブジェクトのプロパティ(定義済)
  • オブジェクトのプロパティ(未定義)

例1:プリミティブな変数をv-ifに指定した場合

<template>
  <div>
    <button @click="show">表示する</button>
    <p v-if="isShow">クリックされました</p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      isShow: false,
    }
  },
  methods: {
    show () {
      this.isShow = true
    }
  }
};
</script>

このケースの場合は、ボタンをクリックすると、期待通りクリックされましたの文言が画面に表示されます。

Kapture 2021-02-04 at 02.48.05.gif

例2:オブジェクトのプロパティ(定義済)をv-ifに指定した場合

<template>
  <div>
    <button @click="show">表示する</button>
    <p v-if="hoge.isShow">表示</p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      hoge: {
        isShow: false,
      }
    }
  },
  methods: {
    show () {
      this.hoge.isShow = true
    }
  }
};
</script>

この場合も、ボタンをクリックすると、期待通りクリックされましたの文言が画面に表示されます。

例3:オブジェクトのプロパティ(未定義)をv-ifに指定した場合

<template>
  <div>
    <button @click="show">表示する</button>
    <p v-if="hoge.isShow">表示</p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      hoge: {
        // isShow: false, コメントアウトで未定義にしています
      }
    }
  },
  methods: {
    show () {
      this.hoge.isShow = true
    }
  }
};
</script>

この場合、初期表示時点では期待通り、文言が表示されていません。(コンソールにもエラーは吐かれません。)

では、ボタンをクリックしてみます。
Kapture 2021-02-04 at 02.56.36.gif

この場合、this.hoge.isShow = trueの処理が実行されるのですが、クリックされました。の文言は表示されません。解説・理由は以下の通りです。

オブジェクトのプロパティを追加してもリアクティブに動作しない

Vueはコンポーネント生成時(onCreate時)のデータに対して変更検出を行うため、生成時に未定義のプロパティが後から追加されても、リアクティブなプロパティとして動作させることができません。

https://vuejs.org/v2/guide/reactivity.html#For-Objects
# For Objects
Vue cannot detect property addition or deletion. ...

解決策

例3のような、オブジェクトのプロパティ追加時でもリアクティブに動作させるには、Vue.setを利用します。

  • Vue.set(object, propertyName, value)の使用
    • 第1引数: 追加したいオブジェクト
    • 第2引数: 追加したいプロパティ名
    • 第3引数: プロパティの値

Vue.setのエイリアスのthis.$setを利用して、例3の場合でもリアクティブに動作するよう実装してみる。

<template>
  <div>
    <button @click="show">表示する</button>
    <p v-if="hoge.isShow">表示</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      hoge: {
        // isShow: false, コメントアウトで未定義にしています
      }
    };
  },
  methods: {
    show() {
      this.$set(this.hoge, "isShow", true);
    }
  }
};
</script>

Kapture 2021-02-04 at 02.48.05.gif

this.hogeisShow (true)が追加されたことをVueが検知できるので、クリックされました。の文言が無事に表示されました。🙌

補足

Vue3では、オブジェクトのプロパティ追加時でもリアクティブに動作する新仕様になっているっぽいので、技術調査したら改めて記事にしようと思います。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?