前言
父子元件之間的雙向繫結非常簡單,但是很多人因為是從Vue 2+開始使用的,可能不知道如何雙向繫結,當然最簡單的雙向繫結(單檔案中)就是表單元素的v-model
了,例如<input type="text" />
它會響應表單元素的value
屬性,當輸入框文字改變時,會將value
值傳給v-model
所繫結的變數,如果同時設定v-model
和value
,value
屬性無效。
歡迎來我的Vue技術群交流:887516034
父子元件的自定義雙向v-model
當若干dom封裝成元件時,在父元件中使用子元件時,卻無法在子元件標籤上使用v-model
,因為子元件標籤不是表單元素,這個時候,我們需要自定義我們想要的v-model
規則。
<!-- children.vue -->
<template>
<h1>{{ msg }}</h1>
</template>
<script>
export default{
model:{
prop:'msg',//這個欄位,是指父元件設定 v-model 時,將變數值傳給子元件的 msg
event:'parent-event'//這個欄位,是指父元件監聽 parent-event 事件
},
props:{
msg:String //此處必須定義和model的prop相同的props,因為v-model會傳值給子元件
},
mounted(){
//這裡模擬非同步將msg傳到父元件v-model,實現雙向控制
setTimeout(_=>{
let some = '3秒後出現的某個值';//子元件自己的某個值
this.$emit('parent-event',some);
//將這個值通過 emit 觸發parent-event,將some傳遞給父元件的v-model繫結的變數
},3000);
}
}
</script>
複製程式碼
<!-- parent.vue -->
<template>
<children v-model="parentMsg"></children>
</template>
<script>
import children from 'path/to/children.vue';
export default{
components:{
children
},
data(){
return{
parentMsg:'test'
}
},
watch:{
parentMsg(newV,oldV){
console.log(newV,oldV);
//三秒後控制檯會輸出
//'3秒後出現的某個值','test'
}
}
}
</script>
複製程式碼
你學會元件的自定義
v-model
了嗎 ? 如果是普通的表單元素,同理,監聽表單的input
或者change
事件,實時將value
或者checked
通過$emit
傳遞就可以了。
父子元件的自定義多個雙向值
上述例子,是實現單個prop值的雙向繫結,當元件的需求需要複雜的操作,需要多個雙向值,是如何實現的呢。這裡需要用到以前被vue拋棄,後來又迴歸的.sync
修飾符。
事實上,這個比v-model
更加簡單
<!-- children.vue -->
<template>
<h1>{{ msg }}</h1>
</template>
<script>
export default{
props:{
msg:String
},
mounted(){
//這裡模擬非同步將msg傳到父元件v-model,實現雙向控制
setTimeout(_=>{
let some = '3秒後出現的某個值';//子元件自己的某個值
this.$emit('update:msg',some);
//將這個值通過 emit
//update為固定欄位,通過冒號連線雙向繫結的msg,將some傳遞給父元件的v-model繫結的變數
},3000);
}
}
</script>
複製程式碼
<!-- parent.vue -->
<template>
<children :msg.sync="parentMsg"></children>
<!-- 此處只需在平時常用的單向傳值上加上.sync修飾符 -->
</template>
<script>
import children from 'path/to/children.vue';
export default{
components:{
children
},
data(){
return{
parentMsg:'test'
}
},
watch:{
parentMsg(newV,oldV){
console.log(newV,oldV);
//三秒後控制檯會輸出
//'3秒後出現的某個值','test'
}
}
}
</script>
複製程式碼
此處需要注意,雖然加上.sync
即可雙向繫結,但是還是要依靠子元件$emit
去觸發update:prop名
實現修改父元件的變數值實現雙向資料流,如果直接對prop的屬性直接賦值,依然會出現報錯。
事實上,.sync
修飾符是一個簡寫,它做了一件事情
<template>
<children :msg.sync="parentMsg"></children>
<!-- 等價於 -->
<children :msg="parentMsg" @update:msg="parentMsg = $event"></children>
<!-- 這裡的$event就是子元件$emit傳遞的引數 -->
</template>
複製程式碼
當需要把一個物件中的屬性全部通過.sync
傳入雙向資料流時,可以再簡便一下寫法
<template>
<children :.sync="obj"></children>
</template>
<script>
export default{
components:{
children
},
data(){
return{
obj:{
parentMsg:'test'
}
}
}
}
</script>
複製程式碼
當使用這種寫法時,會將obj物件中的所有屬性都通過獨立的props傳遞給子元件,並監聽對應的update:
,此時在子元件中也要宣告對應的props。
總結
在父子元件中,使用雙向資料流,在某些時候,能夠起到很好效果,以及開發體驗,不過一定要適量使用,雙向資料流會給專案的後期維護增加負擔。
tips:懂得分享才會走得更遠。
歡迎來我的Vue技術群交流:887516034
如果覺得對你有用,就打賞一下吧。