無論是vue還是react,在父子組件通訊的時候,子組件都禁止直接修改父級傳過來的prop,父組件總需要在子組件身上監聽一個事件,然后由子組件去觸發它,好讓父組件來接收到payload去改變state。幸運的是,vue為我們准備了兩個語法糖,讓我們減少了一點寫大量模板代碼的痛苦。它們就是自定義組件上的v-model
指令以及.sync
修飾符。
假如我們有如下的一個父組件,想為子組件傳遞一個名為val的prop,並且期待有雙向綁定的效果:
<template>
<child-component :val="val" />
</template>
<script>
export default {
data() {
return {
val: 100
}
}
}
</script>
而子組件負責接收val,並且每click一次button,則讓val+2:
<template>
<div>
<div>{{val}}</div>
<button @click="handleClick">click</button>
</div>
</template>
通過v-model
一個組件上的 v-model 默認會利用名為 value
的 prop 和名為 input
的事件,但是像單選框、復選框等類型的輸入控件可能會將 value attribute
用於不同的目的。利用model
選項可以用來避免這樣的沖突。換句話說,你可以將v-model
的prop以任意名稱來接收,不一定要使用value
, 事件名稱也可以是任意的,不一定非要寫成input
。如下例:
父組件通過v-model傳遞val值:
<template>
<child-component v-model="val" />
</template>
而子組件內通過model
選項去綁定這個prop:
export default {
model: {
prop: 'anyKey', // 不一定非要是value
event: 'anyEventName' // 不一定非要是input
},
props: {
anyKey: {
type: Number
}
},
methods: {
handleClick() {
this.$emit('anyEventName', this.anyKey+2)
}
}
}
通過.sync修飾符
父組件通過.sync修飾符傳遞val值:
<template>
<child-component :val.sync="val" />
</template>
子組件內接收更簡單,因為vue內部幫我們綁定了update:myPropName
這樣一個事件:
export default {
props: {
val: {
type: Number
}
},
methods: {
handleClick() {
this.$emit('update:val', this.val+2)
}
}
}
.sync
修飾符寫起來更簡便一些,雙向綁定爽歪歪。不過有一點要注意,像v-bind.sync=”{ title: doc.title }”
這種綁定字面量對象,修飾符是無法正常工作的。