Vue.js进阶系列(7)--组件通信结合双向绑定

  在前面,小编已经陆陆续续为大家分享了很多知识点,那么今天要为大家分享的是将组件通信和双向绑定结合在一起。这个案例的需求是这样子的:
1.基本数据:父组件有数据num1和num2,子组件有数据number1和number2.
2.实现需求:
  ① 父传子:将父组件的num1和num2传递到子组件的numer1和number2;
  ② 双向绑定:通过input输入框实现子组件的number1和number2的双向绑定;
  ③子传父:将新的number1和number2传递到父组件的num1和num2中。
那么下面开始编写代码

一、父传子

结合我们前面学过的知识,父传子是通过props实现的,具体代码如下:

    <body>
        <!-- 父组件Vue实例模板 -->
        <div class="warp">
            <!-- 通过v-bind传递数据 -->
            <cnp :number1="num1" :number2="num2"></cnp>
        </div>
        
        <!-- 子组件cnp的模板 -->
        <template id="tem">
            <div>
                <h2>props:{{number1}}</h2>
                <h2>props:{{number2}}</h2>
            </div>
        </template>
        
        <script>
            
            var vm = new Vue({
                el:'.warp',
                data:{
                    num1:1,
                    num2:2
                },
                
                // 子组件的注册
                components:{
                    cnp:{
                        template:'#tem',
                        props:{
                            number1:Number,
                            number2:Number
                        }
                    }
                }
            })
        </script>
    </body>

  在本例中,依旧将Vue作为父组件,父组件data中的数据分别是num1和num2;将子组件cnp声明为局部组件,子组件内部的数据分别是number1和number2;然后在父组件的模板div中使用子组件cnp并通过v-bind执行将num1传递给number1,将num2传递给number2.需求①已经完成

二、双向绑定

  这个需求是,我们希望在输入框输入什么数字就将该数字传递到子组件中,通过v-model实现,编写代码如下:

<template id="tem">
    <div>
        <h2>props:{{number1}}</h2>
        <input type="text" v-model="number1">

        <h2>props:{{number2}}</h2>
        <input type="text" v-model="number2">
    </div>
</template>
双向绑定.gif

  没错,就是这个效果!实现的非常完美!下面继续第三个需求。正当小编十分开心准备实现下一个需求时,发生了不可思议的事情,令小编十分的震惊!!!那就是居然在控制台上有错!!!!!!


你为什么错?.JPG

没办法,知错就改,这是为人的准则对吧,让我们先来看看到底是什么错误

image.png

  嗯?什么?你看不懂?没关系,小编刚去百度了,这个的意思就是说当你使用v-model实现一些双向绑定的时候,是不可以修改props的数据的,应该使用data或者computed计算属性
  因为props的数据是由父组件传递过来的,如果用v-model也可以修改props中的数据,就意味着props的数据来源不单单有父组件,还有通过v-model实现的双向绑定的数据。
  试想一下,你男朋友前脚收了你的礼物,又背着你收了别的女生的礼物,这是绝对不允许的!你男朋友只能收你的礼物不准收其他女孩子的礼物!props也一样,数据来源只能是父组件。
image.png

  所以我们应该这样做:首先在子组件用data函数来接受props中的数据,然后v-model绑定的是子组件中data的变量。代码如下:

// ①第一步:用data函数接收props中要修改的数据
data(){
        return{
                dnumber1:this.number1,
                dnumber2:this.number2
        }                   
}
//②第二步: v-model绑定子组件中data的数据
<template id="tem">
    <div>
        <h2>props:{{number1}}</h2>
        <h2>data:{{dnumber1}}</h2>
        <input type="text" v-model="dnumber1">

        <h2>props:{{number2}}</h2>
        <h2>data:{{dnumber2}}</h2>
        <input type="text" v-model="dnumber2">
    </div>
</template>
//这段代码可以直接添加到components组件中,为方便观看,小编已经为你拨开了被上帝遮住的眼(#^.^#)

  在子组件的data函数声明了两个变量dnumber1、dnumber2来接收存放props中的number1、number2,然后在子组件的模板中,用v-model绑定dnumber1和dnumber2.效果如下:


正确的双向绑定.gif

  完美,data值随着输入框的改变而改变了。好啦,我知道你要说什么,props的值没有改变,因为这是下面的需求啦~

三、子传父

  想要props的值改变,就意味着父组件的数据也要改变,因为props的值是父组件传递过来的,所以我们要将子组件中变化的dnumber1和dnumber2的值传递到父组件中去。【子传父的三步骤是:发射--接收--处理】
  首先我们知道,v-model的本质是v-bind指令和input事件的组合【别问我为啥知道,因为我在 “Vue.js入门系列(8)--表单操作1 https://www.jianshu.com/p/e005fef1c3eb” 讲过,不认真听讲是要打小屁屁的╭(╯^╰)╮】,所以我们将上述 的v-model修改成下面的形式:

<!-- <input type="text" v-model="dnumber1"> -->
<input type="text" :value='dnumber1' @input='num1Input'>
<!-- <input type="text" v-model="dnumber2"> -->
<input type="text" v-model="dnumber2" @input='num2Input'>

  没错,就像你发现的,这里有input事件,我们将在input事件内部发射自定义的事件给父组件,具体代码如下:

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);
    }
}

  呼叫父组件!呼叫父组件!发射事件成功!请注意接收。【下面是父组件接收事件的代码】

<div class="warp">
    <cnp :number1="num1" :number2="num2" 
        @num1change='numchange1' 
        @num2change='numchange2'/>
</div>

  接收成功!!接收成功!!正在紧急处理中...【下面是父组件对事件的处理】

methods:{
    numchange1(value){
        this.num1=value
    },
    numchange2(value){
        this.num2=value
    }
}
//注意哦!这个是Vue中的methods,不是component的methods

好了,万事俱备只欠东风!让我们一起嗨起来吧!

子传父.gif

成功了!小编简直就是天使!
image.png

诶?!不对,又有错!!!!!
image.png

  好吧,我知道你们看不懂,这次小编真的没有查百度,完全是靠着智慧取胜的!意思就是number1在传递给value的时候发生类型错误,默认情况下value传递的是string。你还别不信,因为下面有犯罪证据:
image.png

打印的时候确实是string类型,这个时候只需要通过parseInt转换就好了

methods:{
    numchange1(value){
        this.num1=parseInt(value)
    },
    numchange2(value){
        this.num2=parseInt(value)
    }
},

到目前为止,我们已经......等等等等,小编忘记放整个代码了

    <body>
        <!-- 父组件Vue实例模板 -->
        <div class="warp">
            <!-- 如果cnp没有内容的话,可以使用单标签也就是<cnp></cnp>==><cnp/>-->
            <cnp :number1="num1" :number2="num2" 
                @num1change='numchange1' 
                @num2change='numchange2'/>
        </div>
        <!-- 子组件cnp的模板 -->
        <template id="tem">
            <div>
                <h2>props:{{number1}}</h2>
                <h2>data:{{dnumber1}}</h2>      
                <!-- v-model 的实质是v-bind 和 input事件 -->
                <!-- 将value的值动态传递给dnumber1,当输入框发生改变时,就会触发num1Input事件 -->
                <input type="text" :value='dnumber1' @input='num1Input'>
                <h2>props:{{number2}}</h2>
                <h2>data:{{dnumber2}}</h2>
                <input type="text" v-model="dnumber2" @input='num2Input'>
            </div>
        </template> 
        <script>        
            var vm = new Vue({
                el:'.warp',
                data:{
                    num1:1,
                    num2:2
                },
                methods:{
                    // 父组件接收子组件发送的时间做的处理:将子组件发送的dnumber1赋值给num1
                    numchange1(value){
                        this.num1=parseInt(value)
                    },
                    numchange2(value){
                        this.num2=parseInt(value)
                    }
                },          
                // 子组件的注册
                components:{
                    cnp:{
                        template:'#tem',
                        props:{
                            number1:Number,
                            number2:Number
                        },
                        // 用data函数替代props中要修改的数据
                        data(){
                            return{
                                dnumber1:this.number1,
                                dnumber2:this.number2
                            }                       
                        },
                        methods:{
                            num1Input(event){
                                // 将输入框的值赋值给dnumber1
                                this.dnumber1=event.target.value;
                                // 对父组件发送num1change时间的同时传递dnumber1
                                this.$emit('num1change',this.dnumber1);
                            },
                            num2Input(event){
                                this.dnumber2=event.target.value;
                                this.$emit('num2change',this.dnumber2);
                            }
                        }
                    }
                }
            })
        </script>
    </body>

  到目前为止,就是小编今天为大家分享的组件通信和双向绑定的综合案例,虽然在实际的项目开发过程中很少会碰到这个绕的传递方式
  但是你要记住!在IT行业,林子大了,什么客户都有,所有为了以后的幸福着想,现在还是得绕点路。谢谢大家的支持!
(虽然做好了没有什么人看也没有什么人点赞的准备,但是还是要精心的为你们准备每日的干货O(∩_∩)O)
❤❤祝大家好梦φ( ̄∇ ̄o)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,589评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,615评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,933评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,976评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,999评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,775评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,474评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,359评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,854评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,007评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,146评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,826评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,484评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,029评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,153评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,420评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,107评论 2 356