在前面,小编已经陆陆续续为大家分享了很多知识点,那么今天要为大家分享的是将组件通信和双向绑定结合在一起。这个案例的需求是这样子的:
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>
没错,就是这个效果!实现的非常完美!下面继续第三个需求。正当小编十分开心准备实现下一个需求时,发生了不可思议的事情,令小编十分的震惊!!!那就是居然在控制台上有错!!!!!!
没办法,知错就改,这是为人的准则对吧,让我们先来看看到底是什么错误
嗯?什么?你看不懂?没关系,小编刚去百度了,这个的意思就是说当你使用v-model实现一些双向绑定的时候,是不可以修改props的数据的,应该使用data或者computed计算属性。
因为props的数据是由父组件传递过来的,如果用v-model也可以修改props中的数据,就意味着props的数据来源不单单有父组件,还有通过v-model实现的双向绑定的数据。
试想一下,你男朋友前脚收了你的礼物,又背着你收了别的女生的礼物,这是绝对不允许的!你男朋友只能收你的礼物不准收其他女孩子的礼物!props也一样,数据来源只能是父组件。
所以我们应该这样做:首先在子组件用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.效果如下:
完美,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
好了,万事俱备只欠东风!让我们一起嗨起来吧!
成功了!小编简直就是天使!
诶?!不对,又有错!!!!!
好吧,我知道你们看不懂,这次小编真的没有查百度,完全是靠着智慧取胜的!意思就是number1在传递给value的时候发生类型错误,默认情况下value传递的是string。你还别不信,因为下面有犯罪证据:
打印的时候确实是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)