由於 Prop 是以 Object 形式呈現,會直覺想用 Object Destructure 將其解構,但這會使得 Prop 喪失 Reactivity,必須透過 toRefs()
再 Destructure。
Version
Vue 3.4.0
toRefs()
- Prop 不只提供 component 的初始值,之後外部 state 變動也會影響 component 內部 state
App.vue
<template>
<div>
<button @click="onClick">Outer +</button>
<span>External State: {{ count }}</span>
</div>
<MyCounter :initialCount="count" />
</template>
<script setup>
import { ref } from 'vue'
import MyCounter from '@/components/MyCounter.vue'
let count = ref(10)
let onClick = () => count.value++
</script>
Line 2
<div>
<button @click="onClick">Outer +</button>
<span>External State: {{ count }}</span>
</div>
- 外部 state 可不斷遞增
Line 6
<MyCounter :initialCount="count" />
- 外部 state 透過
initialCount
prop 傳進MyCounter
component
MyCounter.vue
<template>
<div class="box">Internal State: {{ count }}</div>
</template>
<script setup>
import { computed, toRefs } from 'vue'
let props = defineProps({ initialCount: Number })
let { initialCount } = toRefs(props)
let count = computed(() => initialCount.value * 10)
</script>
<style scoped>
.box {
border-style: solid;
border-width: 2px;
border-color: red;
width: fit-content;
}
</style>
Line 8
let props = defineProps({ initialCount: Number })
let { initialCount } = toRefs(props)
let count = computed(() => initialCount.value * 10)
defineProps()
:定義initialCount
proptoRefs()
:將 reactive object 轉成一般 Object,但每個 property 都是ref
,如此 Object Destructure 之後才不會喪失 reactivitycomputed()
:在computed()
內讀取 prop 並加工,因為使用了computed()
,所以count
state 與initialCount
prop 有連動性
Conclusion
- 這是 Vue 3 初學者很容易遇到的地雷,若要對 prop 使用 Object Destructuring 且維持 reactivity,別忘了加上
toRefs()