最近做了一個完整的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>
這是我根據經驗總結出來的,可能會有不准確的地方,大家可以根據自己的理解使用。