在前面的章节中小编已经为大家分享了什么是父组件和子组件,接下来小编将为大家分享父组件和子组件之间的通信
一、通信产生的原因
在正常的开发过程中,我们从服务器获取到了大量数据。其中一部分数据并不是显示整个页面的大组件中,而是需要在下面的子组件进行展示。这个时候并不是让子组件再次发送数据请求信息给服务器,而是让大组件向服务器请求信息并将数据传递给小组件。比如看下面的例子:
下面我们从父组件和子组件两个方面来分析为何父组件和子组件之间要有通信
① 父组件:如上图所示,我们想要获取小组件内容的数据,必须向服务器发送数据请求信息,而向服务器发送数据请求信息的是页面大组件(父组件)而不是小组件。如果是小组件获取数据,对于图中的5个小组件就要向服务器请求5次,如果是父组件,仅仅只需要一次,为了避免服务器不瘫痪,使用父组件向服务器发送请求信息并获取数据,将获取到的数据放在父组件的data中。
② 子组件:由于子组件不能获取父组件或者Vue实例中的data数据,那么子组件如果想要获取在父组件data中的数据就必须通过另外一种方式,而这种方式就是父组件和子组件之间的通信
二、如何进行通信
在进行父子组件之间的通信时,有下面两种方式:
① 父传子:通过props
② 子传父:通过自定义事件
在这里小编先讲解父组件传递给子组件
1.props书写步骤
在本次案例中,为避免组件数量过多,小编将Vue当做父组件【前面提到过,Vue实例是root组件,可以当做所有组件的父组件】,为了方便理解,小编从两个步骤说明如何实现父传子
①书写父组件和子组件的基本构造:
就像我们平常书写父子组件一样
<template id="tem">
<div>
<h2>我是标题</h2>
<p>我是段落</p>
</div>
</template>
<script>
var vm = new Vue({
el:'.warp',
data:{
message:'我是标题',
movies:['海贼王','海王','海尔兄弟']
},
components:{
cnp:{
template:'#tem',
},
}
})
</script>
代码分析如下:
1.1 父组件:Vue实例作为父组件,其中的messag和movies存放父组件从服务器获取的数据【当然,小编这个没有连接服务器,只是为了以后真正从服务器获取数据时能知道数据存放在哪里】
1.2 子组件:使用语法糖的格式声明了局部组件cnp,并且通过模板抽离将template的模板的内容抽离到template标签中,两者通过tem id名来建立起联系
那么下一步,小编就将父组件中的数据通过props传递到子组件中
② 通过props实现父组件和子组件之间的通信:
<div class="warp">
<cnp v-bind:cmessage='message' v-bind:cmovies='movies'></cnp>
</div>
<template id="tem">
<div>
<h2>{{cmessage}}</h2>
<p>{{cmovies}}</p>
</div>
</template>
components:{
cnp:{
template:'#tem',
props:['cmessage','cmovies']
},
}
<!--为了便于代码的观看,其余部分已经被小编删除,后序会有完整的代码 -->
2.1 使用props声明变量:props的写法和Vue实例中methods的写法很相似,只不过这里小编用数组来存放变量,这个变量就是后期要引用的变量名
2.2 通过v-bind实现通信:在使用<cnp></cnp>标签引用组件时,为了将Vue实例中的数据传递到cnp组件中,使用v-bind操作cmessage属性和cmovies属性,引用上一步声明的变量名cmessage和cmovies,接着为变量赋值cmessage='message'和cmovies='movies'
2.3 显示数据: 经过前两个步骤,数据已经从Vue传递到cnp子组件中,接下来就是在子组件的模板template中引用子组件声明的变量名即可,比如本例子引用cmessage和cmovies
注意:不能引用Vue实例中的message和movies,因为子组件是不能操作父组件的数据
下面是完成的代码和效果:
<body>
<div class="warp">
<cnp v-bind:cmessage='message' v-bind:cmovies='movies'></cnp>
</div>
<template id="tem">
<div>
<h2>{{cmessage}}</h2>
<p>{{cmovies}}</p>
</div>
</template>
<script src="vue.min.js" ></script>
<script>
var vm = new Vue({
el:'.warp',
data:{
message:'我是标题',
movies:['海贼王','海王','海尔兄弟']
},
components:{
cnp:{
template:'#tem',
props:['cmessage','cmovies']
},
}
})
</script>
</body>
可以看到数据已经成功的从父组件传递到了子组件中,如果你不想要以数组的形式显示数据,使用v-for指令遍历并显示即可:
<template id="tem" >
<div>
<h2>{{cmessage}}</h2>
<ul v-for="item in cmovies">
<li>{{item}}</li>
</ul>
</div>
</template>
2.props 类型
props支持的类型很多,主要有:String,Number, Boolean, Array, Object, Data, FunctionSymbol。下面小编主要为大家分享数组类型和对象类型 。
① 数组类型
components:{
cnp:{
template:'#tem',
props:['cmessage','cmovies']
}
}
这种写法虽然简洁,但是看起来有点别扭,因为cmessage是一个变量而不是字符串【因为字符串都是用引号包裹着的】,所以一般在开发的过程中,都采用对象类型。
② 对象类型
2.1 基本对象类型
就是在对象内部声明变量的类型,比如:
components:{
cnp:{
template:'#tem',
props:{
cmessage:String,
cmovies:Array
}
}
}
本例中声明cmessage是字符串类型,cmovies是数组类型。
2.2 有默认值的对象类型--default
使用了default属性的变量,在没有被传递数据时,就会显示默认值【如果传递了数据,默认值就被数据覆盖了】。默认值的书写方式又和变量的类型有关,主要分为当变量是String类型和当变量是数组类型或者是对象类型两种情况
2.2.1 变量是String类型
components:{
cnp:{
template:'#tem',
props:{
cmessage:{
type:String,
default:'aaaa'
}
}
}
}
这个例子中,将cmessage的值变成了一个对象,然后在对象内部定义cmessage的类型是String,默认值是aaaa。
2.2.2 变量是数组类型或者对象类型时
当cmessage是数组类型是,如果我们是这样子书写: default:[],在Vue 2.5.17一下是不通过的,比如:
props:{
cmessage:{
type:Array,
default:[]
},
}
默认值是无效的,如果默认值的类型是数组或者对象类型,默认值必须是一个函数,也就是要修改成下面的代码:
props:{
cmessage:{
type:Array,
default(){
return []
}
},
}
此外,就像刚刚开头提到的,如果在使用了default后还传递数据,新数据就会覆盖默认值。比如:
<!-- 没有默认值 -->
<div class="warp">
<cnp v-bind:cmessage='message' v-bind:cmovies='movies'</cnp>
</div>
<!-- 有默认值 -->
<div class="warp">
<cnp v-bind:cmovies='movies'></cnp>
</div>
默认值aaaa已经被“我是标题”覆盖了
2.3 有必传值的对象类型--require
当组件中的变量使用required属性时,意味着别人使用这个组件一定要给该变量传递数据,否则就会把报错,比如:
<div class="warp">
<cnp></cnp>
</div>
components:{
cnp:{
template:'#tem',
props:{
cmessage:{
type:String,
required:true
}
}
}
}
在组件cnp的变量cmessage中使用了required属性,但是在使用组件cnp时,并没有给cmessage传递数值,这时就会报错 ,因此,如果使用了required属性时,一定要给变量传递数据,比如:
<!-- 有给cmessage传递数据 -->
<div class="warp">
<cnp v-bind:cmessage='message'></cnp>
</div>
<!-- 没有给cmessage传递数据 -->
<div class="warp">
<cnp></cnp>
</div>
3.props 驼峰标识
所谓的驼峰标识其实就是指两个单词拼接在一起,第二个单词的首字母是大写。比如:myMovies就是驼峰标识。
在Vue中,使用v-bind指令,是不支持驼峰标识的,需要将第二个单词的首字母用 “ 横线 小写"代替”。比如:
<div class="warp">
<cnp :cMessage="message"></cnp>
</div>
<template id="tem" >
<div>
<p>{{cMessage}}</p>
</div>
</template>
<script>
var vm = new Vue({
el:'.warp',
data:{
message:'我是标题',
movies:['海贼王','海王','海尔兄弟']
},
components:{
cnp:{
template:'#tem',
props:{
cMessage:{
type:String,
default:'aaaa',
}
}
}
}
})
</script>
在这个例子中,我们希望就父组件Vue中的message数据传递到子组件cnp的cMessage中,但是从效果图中可以看到,并没有传递成功。这是因为在子组件使用v-bind指令操作变量时,变量使用的是驼峰标识【<cnp :cMessage="message"></cnp>】,在目前Vue的版本中是不允许的,因此需要将cMessage修改成“c-message”
<div class="warp">
<cnp :c-message="message"></cnp>
</div>
如果变量名是 cMyLoveMovies,同理,需要修改成“c-my-love-movies”
好了,以上就是小编今天为大家分享的干货,总结成以下几点:
1.通信目的:为了减少访问服务器是访问频率
2.props的书写方式
2.props的类型很多种,这里主要讲了数组和对象两种类型
2.1 当props是对象类型时,可以有type,default,required属性
2.2 default是字符串时的写法和default是数组或者对象的写法.
3.props的驼峰标识