vue props雙向數據綁定方案


最近做了一個完整的vue項目,對父子組件之間的數據傳遞新的用法有了更深的了解,現在記錄一下。

雖然標題是實現props 雙向數據綁定 其實VUE是 不支持props數據雙向綁定的,但是我們可以模擬雙向綁定的樣式,主要是為了簡化數據更改及父子節點之前數據同步的操作

 

 

第一種方式 v-model 的方式。

原理:利用v-model指令把數據綁定到子組件中,然后子組件中模擬普通文本框的input事件,來傳遞修改之后的值。

v-model的雙向數據綁定的基本原理就是監聽了文本框的input事件,通過監聽input事件得知數據被修改了,所以我們可以觸發自定義input事件,這樣v-model這個指令就能監聽到數據的變化。

例子:

//Parent.vue
<template>
    <div class="box">
        <p>發給child的modelMSG: {{modelMSG.msg}}</p>
        <p>
            修改modelMSG:
            <input type="text" v-model="modelMSG.msg" />
        </p>
        <Child v-model="modelMSG" />
    </div>
</template>

<script>
import Child from './Child'
export default {
    name: 'Parent',
    components: {
        Child,
    },
    data() {
        return {
            modelMSG: {//這里故意寫成對象格式的,目的是表明v-model可以傳遞對象,這樣就可以傳遞多種數據了
                msg: '發給Child的modelMSG信息',
            },
            name: 'Parent的名字',
        }
    },
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
h3 {
    margin: 40px 0 0;
}
ul {
    list-style-type: none;
    padding: 0;
}
li {
    display: inline-block;
    margin: 0 10px;
}
.green {
    color: #42b983;
}
.box {
    text-align: left;
    width: 600px;
    margin: 0 auto;
}
input {
    width: 200px;
    height: 35px;
    line-height: 35px;
}
</style>

注意: v-model="modelMSG" 這里的modelMSG我是故意寫成對象格式的,目的是為了表明v-model可以傳對象過去,這樣就可以傳遞多個數據了。

 

 

//Child.vue
<template>
    <div class="hello">
        <p class="red">來自Parent的value: {{value.msg}}</p>
        <p>
            <input v-model="parentModelMSG" type="text" />
        </p>
    </div>
</template>

<script>
export default {
    name: 'Child',
    props: {
        value: Object, //注意子組件接收數據時用value接收,這里的value代表 parentModelMSG
    },
    data() {
        return {
            name: '',
            parentModelMSG: this.value.msg,
        }
    },
    watch: {
        parentModelMSG() {
            this.$emit('input', { //這里也是必要的,目的是子組件修改數據的時候回傳到父組件
                msg: this.parentModelMSG,
            })
        },
        'value.msg1'() { //這塊是為了監聽父組件變化的時候同步parentModelMSG信息,也可以用deep的方式 value: {deep: true, handler(){ ... }},這樣可以監聽所有數據修改 this.parentModelMSG = this.value.msg
        },
    },
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
    margin: 40px 0 0;
}
ul {
    list-style-type: none;
    padding: 0;
}
li {
    display: inline-block;
    margin: 0 10px;
}
.red {
    color: #f00;
}
</style>

 注意:v-model設置的屬性接收時需要用value這個字段接收

 

第二種 .sync 的方式

原理:這其實就是普通傳遞數據和監聽事件的一種簡寫方式而已, 這個方式可以算是官方給出的一種props雙向綁定的一種解決方案

例子:

//Parent.vue
<template>
    <div class="box">
        <p>發給child的modelMSG: {{modelMSG.msg}}</p>
        <p>
            修改modelMSG:
            <input type="text" v-model="modelMSG.msg" />
        </p>
        <Child :data.sync="modelMSG" /> //這里:data.sync其實就是 :data="modelMSG"  @update:data="(value) => { this.data = value }"
    </div>
</template>

<script>
import Child from './Child'
export default {
    name: 'Parent',
    components: {
        Child,
    },
    data() {
        return {
            modelMSG: {
                msg: '發給Child的modelMSG信息',
            },
            name: 'Parent的名字',
        }
    },
}
</script>
//Child.vue
<template>
    <div class="hello">
        <p class="red">來自Parent的value: {{data.msg}}</p>
        <p>
            <input v-model="parentModelMSG" type="text" />
        </p>
    </div>
</template>

<script>
export default {
    name: 'Child',
    props: {
        data: Object,
    },
    data() {
        return {
            name: '',
            parentModelMSG: this.data.msg,
        }
    },
    watch: {
        parentModelMSG() {
            this.$emit('update:data', {
                //注意這個事件的格式是`update:${屬性名}`這個屬性名就是props那個key
                msg: this.parentModelMSG,
            })
        },
        data: {
            //data改變的時候同步到子組件
            deep: true,
            handler(value) {
                this.parentModelMSG = value.msg
            },
        },
    },
}
</script>

 這是我根據經驗總結出來的,可能會有不准確的地方,大家可以根據自己的理解使用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM