父子组件通信双向绑定

942 阅读1分钟

将父传子,子传父稍微结合一下,实现父子组件通信双向绑定。最终实现在子组件的输入框中输入数据,实时改变父组件中的数据

同样的,先注册子组件和父组件

const cpn = {
            template: '#cnp',

            props:{
                num1:Number,
                num2:Number
            },

        }
        const app = new Vue({
            el: "#app",
            data: {
                number1:1,
                number2:0
            },
            components: {
                cpn
            },
        })
    <template id="cnp">
        <div>

            <h2>data:{{num1}}</h2>
            <!-- v-model 等于  :value=''+ @input=' =$event.target.value'-->

            <input type="text" :value='dnumber1' @input ='num1Input'>

            <h2>data:{{num2}}</h2>
            <input type="text" :value='dnumber2' @input ='num2Input'>
        </div>
    </template> 
   <div id="app">

//将父组件中的数据绑定到子组件上   
        <cpn 
        :num1='number1'
        :num2='number2'
        >
        </cpn>
    </div>

需要注意的是使用:value中不能直接绑定props中的属性,以免出现数据紊乱,故需要在data中重新注册数据,然后对data中的数据进行修改

 const cpn = {
            template: '#cnp',
            // 避免直接修改props中的值,直接修改可能会导致数据紊乱出错
            data() {
                return {
                    dnumber1:this.num1,
                    dnumber2:this.num2
                }
            },
            props:{
                num1:Number,
                num2:Number
            },
        }

然后子组件中自定义事件,发射给父组件,这里我们把v-model拆开也是为了方便自定义事件( v-model 等于 :value=”+ @input=’ =event.target.value),故我们将@input==event.target.value’ ),故我们将 @input=’ =event.target.value’ 定义为一个新事件

methods:{
                num1Input(event){
                    this.dnumber1 = event.target.value;
                    // 发送事件
                    this.$emit('num1change',this.dnumber1);

                },
                num2Input(event){
                    this.dnumber2 = event.target.value;
                    // 发送事件
                    this.$emit('num2change',this.dnumber2);
                }
            }


<template id="cnp">
        <div>
            <h2>props:{{dnumber1}}</h2>
            <h2>data:{{num1}}</h2>
            <!-- v-model 等于  :value=''+ @input=' =$event.target.value'-->
            <!-- <input type="text" :value='dnumber1' @input ='dnumber1=$event.target.value'> -->
            <input type="text" :value='dnumber1' @input ='num1Input'>
            <h2>props:{{dnumber2}}</h2>
            <h2>data:{{num2}}</h2>
            <input type="text" :value='dnumber2' @input ='num2Input'>
        </div>
    </template> 

发射事件后,需要在父组件中监听,并在父组件中声明做出反应,将dnumber的值付给number,同时number的值就是num的值,故最后实现number和num的值相同并实现实时绑定。

    <div id="app">
        <cpn 
        :num1='number1'
        :num2='number2'

//监听事件
        @num1change ='num1change'
        @num2change ='num2change'
        >
        </cpn>
    </div>
const app = new Vue({
            el: "#app",
            data: {
                number1:1,
                number2:0
            },
            components: {
                cpn
            },
            methods:{
                num1change(value){

//传入的value的类型默认为字符串,通过parsInt()可以将value的类型转化为int类型
                    this.number1 = parseInt(value),
                    //this.number2 = parseInt(value)/10
                },
                num2change(value){
                    this.number2 = parseInt(value),
                    //this.number1 = parseInt(value)*10
                }
            }
        })

当然了,我们还可以使用watch来简化整个过程,我们回到将v-model拆开的部门。如果我们还是想要使用v-model的话,可以使用watch属性来对dnumber进行监听

        const cpn = {
            template: '#cnp',
            // 避免直接修改props中的值,直接修改可能会导致数据紊乱出错
            data() {
                return {
                    dnumber1:this.num1,
                    dnumber2:this.num2
                }
            },
            props:{
                num1:Number,
                num2:Number
            },
            watch:{
                // 检测到dnumber发生变化后就触发事件
                dnumber1(newValue){
                    this.$emit('num1change',this.dnumber1);
                },
                dnumber2(newValue){
                    this.$emit('num1change',this.dnumber2);
                }
            }

其余操作相同。