Vue父子元件如何雙向繫結傳值

chavesgu發表於2018-07-30

前言

父子元件之間的雙向繫結非常簡單,但是很多人因為是從Vue 2+開始使用的,可能不知道如何雙向繫結,當然最簡單的雙向繫結(單檔案中)就是表單元素的v-model了,例如<input type="text" />它會響應表單元素的value屬性,當輸入框文字改變時,會將value值傳給v-model所繫結的變數,如果同時設定v-modelvaluevalue屬性無效。

歡迎來我的Vue技術群交流:Vue887516034

父子元件的自定義雙向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技術群交流:Vue887516034

如果覺得對你有用,就打賞一下吧。

Vue父子元件如何雙向繫結傳值 Vue父子元件如何雙向繫結傳值

相關文章