無論是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 }”
這種綁定字面量對象,修飾符是無法正常工作的。
.sync 和 v-model 的區別
先上結論:兩者的本質都是語法糖,目的都是實現組件與外部數據的雙向綁定。v-model 是 .sync的一種體現。.sync 比較靈活;v-model較單一
v-model只能有一個,(一個組件只有一個model)
個人理解,別的就是語義的區別了,prop.sync
表示這個子組件會修改父組件的值,v-model
表示這是個表單類型
的組件。
v-model一般是表單組件,綁定的是value屬性,這個值的雙向綁定也不是父組件和子組件的關系,而是view和model的對應關系,因為表單組件的值的變化來自於用戶輸入
而sync是指父子組件之間的通信