Vue 允許我們對 HTML Tag 使用 v-model
達成 Two-way Binding,我們除了也可使用 v-model
對 Prop 達成 Two-way Binding 外,也可使用 .sync
。
Version
macOS Catalina 10.15.6
Vue 2.6.11
Custom Event
4
為 outerCount
model,而 inner +
為 MyCounter
內的 button。
outerCount
會傳進 MyCounter
,且當 inner +
遞增時也會 two-way binding 更新 outerCount
。
App.vue
<template>
<div>
{{ outerCount }}
<MyCounter :start-count="outerCount" @update:startCount="onUpdateStartCount"></MyCounter>
</div>
</template>
<script>
import MyCounter from '@/components/MyCounter.vue'
let onUpdateStartCount = function(v) {
this.outerCount = v
}
export default {
data: () => ({
outerCount: 3
}),
components: {
MyCounter
},
methods: {
onUpdateStartCount
}
}
</script>
16 行
data: () => ({
outerCount: 3
}),
定義 outerCount
model,且初始值為 3
。
第 2 行
<div>
{{ outerCount }}
<MyCounter :start-count="outerCount" @update:startCount="onUpdateStartCount"></MyCounter>
</div>
outerCount
除了傳入 <MyCounter>
的 start-count
prop 外,也在外層顯示,因此我們希望 outerCount
能 two-way binding。
MyCounter.vue
<template>
<button @click="onClick">inner +</button>
</template>
<script>
let onClick = function() {
this.$emit('update:startCount', this.startCount +1)
}
export default {
props: [
'startCount'
],
methods: {
onClick
}
}
</script>
11 行
props: [
'startCount'
],
自訂 startCount
prop。
第 6 行
let onClick = function() {
this.$emit('update:startCount', this.startCount +1)
}
自行發出 update:prop名稱
event。
.sync
App.vue
<template>
<div>
{{ outerCount }}
<MyCounter :start-count.sync="outerCount"></MyCounter>
</div>
</template>
<script>
import MyCounter from '@/components/MyCounter.vue'
export default {
data: () => ({
outerCount: 3
}),
components: {
MyCounter
}
}
</script>
第 4 行
<MyCounter :start-count.sync="outerCount"></MyCounter>
雖然可使用 prop 加 event 達成 two-way binding,但也可使用 .sync
modifier,一看就知道 start-count
prop 為 two-way binding,可讀性更高。
MyCounter.vue
<template>
<button @click="onClick">inner +</button>
</template>
<script>
let onClick = function() {
this.$emit('update:startCount', this.startCount +1)
}
export default {
props: [
'startCount'
],
methods: {
onClick
}
}
</script>
第 6 行
let onClick = function() {
this.$emit('update:startCount', this.startCount +1)
}
若要使用 .sync
,Vue 規定一定要發出 update:prop名稱
event。
可發現
.sync
modifier 為 syntatic sugar,也可自行接收 custom event 達成 two-way binding
v-model vs. .sync
v-model
與 .sync
都能達成 prop 的 two-way binding,但有以下差異:
- 一個 component 只能有一個
v-model
,但能有多個.sync
v-model
必須使用value
prop 與input
event;.sync
可自訂 prop 名稱,event 則為update:prop名稱
- 若只有一個 prop 需 two-way binding,建議使用
v-model
;若有多個 prop 需 two-way binding,則可第一個使用v-model
,其他使用.sync
,或者全部使用.sync
Conclusion
- Component 傳遞資料的關鍵在於 prop 與 event,
.sync
的 two-way binding 雖然看似神奇,但骨子裡還是離不開 prop 與 event,prop 名稱可自訂,但 event 則為update:prop名稱
v-model
與.sync
非常類似,目的都是使 prop 能 two-way binding,也因為太類似,Vue 3 已經廢除.sync
,但可同時使用多v-model
,event 則為update:model名稱