Contents
概要
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
が変更されたときにdisplayStatus
をfalse
に設定し、すぐにtrue
に戻しています。これにより、ChildComponent
が再レンダリングされます。