【Vue.js】propsの値を検知してコンポーネントを再レンダリングさせる方法

概要

Vue.jsでは、親コンポーネントから子コンポーネントへデータを渡すためにpropsを使用します。しかし、親コンポーネントでpropsの値が変更されたとき、その変更が子コンポーネントにすぐに反映されない場合があります。
propsの値が変更されたときに子コンポーネントを強制的に再レンダリング(再マウント)させたい時の対処法を2つ紹介します。

Vue.jsの子コンポーネントをリロード・再レンダリングさせる方法

propsの値をwatchで検知してkeyの値を更新する

keyはVue.jsがコンポーネントを追跡し、それが変更されたときに新しいコンポーネントを作成するためのユニークな識別子となっています。keyの値を変更することで、Vue.jsに新しいコンポーネントを作成させ、既存のコンポーネントを再レンダリングさせることができます。

以下に、propsの値が変更されたときにkeyを使って子コンポーネントを再レンダリングする例を示します。

<template>
  <div>
    <Child 
   :key="reload"
   :fruit="props.fruit"
  />
  </div>
</template>

<script>
import Child from './Child.vue'

export default {
  components: {
    Child
  },
  props: {
    fruit: {
      type: String,
      require: false,
      default: 'apple'
    },
  },
  data () {
    return {
      reload: 0
    }
  }, 
  watch: {
    fruit: {
      handler: function() {
        this.reload++
      },
    },
  }
}

propsの値をwatchで検知してv-ifで再レンダリングさせる

v-ifディレクティブは、その条件が真であるときにのみコンポーネントをレンダリングします。
なのでv-ifの条件を変更することで、コンポーネントの再レンダリングをトリガーすることができます。

propsの値をwatchで監視して現在の値と新しく入ってきた値を比較して変わっていたらv-ifで再マウントさせてあげます。

<template>
  <div>
    <ChildComponent 
      v-if="displayStatus" 
      :fruit="fruit" 
    />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  props: {
    fruit: {
      type: String,
      required: false,
      default: 'apple'
    },
  },
  data () {
    return {
      displayStatus: true
    }
  }, 
  watch: {
    fruit: {
      handler(newData, oldData) {
        if (oldData !== newData) {
          this.displayStatus = false
          this.displayStatus = true
        }
      },
      deep: true,
      immediate: false
    }
  }
}
</script>

Composition APIを使用した場合

keyで再マウント

Vue.js 3では、Composition APIという新しい実装方法が主流となっています。
以下に、Composition APIを使用してpropsの値が変更されたときに子コンポーネントを再レンダリングする例を示します。

<template>
  <div>
    <ChildComponent 
      :key="reloadKey.value"
      :fruit="fruit" 
    />
  </div>
</template>

<script>
import { ref, watch } from 'vue'
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  props: {
    fruit: {
      type: String,
      required: false,
      default: 'apple'
    },
  },
  setup(props) {
    const reloadKey = ref(0)

    watch(() => props.fruit, () => {
      reloadKey.value++
    })

    return {
      reloadKey
    }
  }
}
</script>

この例では、setup関数内でwatchを使用してfruit propの変更を監視し、fruitが変更されたときにreloadKeyを増分しています。これにより、ChildComponentが再レンダリングされます。

v-ifで再マウント

Composition APIを使用してv-ifで子コンポーネントを再マウントする方法も以下に示します。

<template>
  <div>
    <ChildComponent 
      v-if="displayStatus.value" 
      :fruit="fruit" 
    />
  </div>
</template>

<script>
import { ref, watch } from 'vue'
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  props: {
    fruit: {
      type: String,
      required: false,
      default: 'apple'
    },
  },
  setup(props) {
    const displayStatus = ref(true)

    watch(() => props.fruit, () => {
      displayStatus.value = false
      displayStatus.value = true
    })

    return {
      displayStatus
    }
  }
}
</script>

この例では、setup関数内でwatchを使用してfruit propの変更を監視し、fruitが変更されたときにdisplayStatusfalseに設定し、すぐにtrueに戻しています。これにより、ChildComponentが再レンダリングされます。

コメントを残す

入力エリアすべてが必須項目です。メールアドレスが公開されることはありません。

内容をご確認の上、送信してください。