若 Prop 只用來對 Component 傳入初始值設定,只要在 mounted
hook 接受並寫入 data
即可;但若日後還會將改變 Data 傳入 Prop,且希望 Component 能 Reactive 根據 Prop 改變,則要搭配 Computed 或 Watch。
Version
Vue 2.6.11
Computed
+
不斷遞增 component 外部的 state,並以 prop 傳入 component 並 reactive 顯示。
App.vue
<template>
<div>
<my-counter :start-count="count"/>
<button @click="onClick">+</button>
</div>
</template>
<script>
import MyCounter from '@/components/MyCounter'
let onClick = function() {
this.count++
}
export default {
components: {
MyCounter
},
data: () => ({
count: 5
}),
methods: {
onClick
}
}
</script>
19 行
data: () => ({
count: 5
}),
將 count
state 初始值設定為 5
。
第 3 行
<my-counter :start-count="count"/>
將 count
state 傳入 start-count
prop。
11 行
let onClick = function() {
this.count++
}
在 component 外對 count
state 遞增,期望 state 改變,連帶著傳進 prop 也能 reactive 改變。
MyCounter.vue
<template>
<div>{{ count }}</div>
</template>
<script>
let count = ({ startCount }) => startCount
export default {
props: {
startCount: { default: 0 }
},
computed: {
count
}
}
</script>
第 9 行
props: {
startCount: { default: 0 }
},
宣告 startCount
prop,且預設值為 0
,也代表其 type 為 Number。
第 6 行
let count = ({ startCount }) => startCount
可從 argument 直接 destructure 出 startCount
prop 回傳產生 count
computed。
為了讓 prop 能 reactive,最簡單的方式是使用 computed
Watch
App.vue
<template>
<div>
<my-counter :start-count="count"/>
<button @click="onClick">+</button>
</div>
</template>
<script>
import MyCounter from '@/components/MyCounter'
let onClick = function() {
this.count++
}
export default {
components: {
MyCounter
},
data: () => ({
count: 5
}),
methods: {
onClick
}
}
</script>
App.vue
部分不變。
MyCounter.vue
<template>
<div>{{ count }}</div>
</template>
<script>
let startCount_ = function(v) {
this.count = v
}
export default {
props: {
startCount: { default: 0 }
},
data: ({ startCount }) => ({
count: startCount
}),
watch: {
startCount: startCount_
}
}
</script>
直接使用 computed 接 prop 雖然可行,但其缺點是不能有 data
。
14 行
data: ({ startCount }) => ({
count: startCount
}),
直接由 argument 解構 startCount
prop,由 prop 初始值定義 count
data。
17 行
watch: {
startCount: startCount_
}
定義 startCount
prop 的 watch,一旦日後 prop 改變,將觸發 startCount_
handler 處理。
第 6 行
let startCount_ = function(v) {
this.count = v
}
一旦 startCount
prop 改變,將其值立即修改 count
data。
若要使用 data,則要先將 prop 初始值給 data,再對 prop 進行 watch
immediate: true
App.vue
<template>
<div>
<MyCounter :start-count="count"/>
<button @click="onClick">+</button>
</div>
</template>
<script>
import MyCounter from '@/components/MyCounter'
let onClick = function() {
this.count++
}
export default {
components: {
MyCounter
},
data: () => ({
count: 5
}),
methods: {
onClick
}
}
</script>
App.vue
部分不變。
MyCounter.vue
<template>
<div>{{ count }}</div>
</template>
<script>
let startCount_ = function(v) {
this.count = v
}
export default {
props: {
startCount: { default: 0 }
},
data: () => ({
count: 0
}),
watch: {
startCount: {
handler: startCount_,
immediate: true
}
}
}
</script>
17 行
watch: {
startCount: {
handler: startCount_,
immediate: true
}
}
若覺得要先由 prop 定義 data 初始值麻煩,也可以在 watch 直接定義 immediate
為 true
,且對 handler
property 定義 startCount_
handler,如此會一併定義 data
初始值。
Conclusion
- 若要 prop 能 reactive,最簡單方式是使用 computed,唯沒有 data 可用
- 若要有 data 也能 reactive, 則要對 prop 使用 watch,先以 prop 定義 data 初始值,再由 watch 將日後改變的 prop 修改 data
- 若想一次由 prop 定義 data 初始值,也可直接在 watch 內定義
immediate: true