在开发中,我们经常会把一些复用率高的代码,封装成一个组件。但是封装组件里面的数据,不能写死,需要动态传入。但是由于在父组件发起的网络请求,所以需要用到组件之间的通信来传递数据。
父传子
首先在父组件里面注册子组件,父组件代码如下:
<template>
<div id="app">
<about></about>
</div>
</template>
<script>
//引入组件
import about from './views/About'
export default {
data(){
return {
}
},
//注册组件
components:{
about,
}
}
</script>
<style lang="scss">
</style>
子组件代码:
<template>
<div class="about">
<h2>姓名:唐僧</h2>
<h2>年龄:88</h2>
</div>
</template>
<script>
export default {
data(){
return {
}
},
methods:{
}
}
</script>
效果图:
在开发中我们经常会遇到,在父组件多次复用这个组件,这也是为什么要封装它的原因。假设父组件引用了三次这个组件。代码如下:
<template>
<div id="app">
<about></about>
<br>
<about></about>
<br>
<about></about>
</div>
</template>
<script>
//引入组件
import about from './views/About'
export default {
data(){
return {
}
},
//注册组件
components:{
about,
}
}
</script>
<style lang="scss">
</style>
效果图:
这时候,需求是每个组件里面的内容,需要根据父组件里面的数据来渲染子组件。这时候就需要用到通信。
首先说下父组件,需要在组件标签里面写一个标签属性,key、value的形式。这个key就是一会子组件用来接收的key,value就是所要传递的数据。
<template>
<div id="app">
<about :name="name1" :age="age1"></about>
<br>
<about :name="name2" :age="age2"></about>
<br>
<about :name="name3" :age="age3"></about>
</div>
</template>
<script>
//引入组件
import about from './views/About'
export default {
data(){
return {
name1:'孙悟空',
age1:66,
name2:'唐僧',
age2:88,
name3:'沙和尚',
age3:99,
}
},
//注册组件
components:{
about,
}
}
</script>
<style lang="scss">
</style>
子组件需要用到props这个配置来接收,代码如下:
<template>
<div class="about">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
</div>
</template>
<script>
export default {
props:['name','age'],
data(){
return {
}
},
methods:{
}
}
</script>
效果图:
需要注意的是,如果需要对父组件传递过来的数据进行修改的时候,最好不要直接对props里面的数据直接进行修改。先赋值给一个变量,在对这个变量进行修改。如下:
<template>
<div class="about">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{userAge}}</h2>
<button @click="addAge">++</button>
</div>
</template>
<script>
export default {
props:['name','age'],
data(){
return {
userAge:this.age
}
},
methods:{
addAge(){
this.userAge++
}
}
}
</script>
props还有其他两种写法:
1.可以限制父组件传递过来数据的类型做限制
2.限制类型的同时,可以限制父组件这个属性是否必传以及给一个默认值
代码如下:
<template>
<div class="about">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{userAge}}</h2>
<button @click="addAge">++</button>
</div>
</template>
<script>
export default {
//第一种写法:简单的接收方式
// props:['name','age'],
//第二种写法:接收的同时对父组件传递的数据做类型限制
// props:{
// name:String,//限制name为字符串类型
// age:Number//限制age为数字类型
// },
// 第三种写法
props:{
name:{
type:String,//限制name为字符串类型
required:true//限制name值必传
},
age:{
type: Number,//限制age为数字类型
default:100,//如果父组件未传值,则默认值为100
}
},
data(){
return {
userAge:this.age
}
},
methods:{
addAge(){
this.userAge++
}
}
}
</script>
子传父
子组件传父组件有两种传值的方法:
第一种,通过父组件给子组件传递函数类型的props实现。
首先还是在组件标签上自定义属性,但是value值传的是一个函数。当子组件接收这个函数,并调用父组件这个函数并传入形参。这时候父组件就可以拿到子组件传递的参数。代码如下:
父组件:
<template>
<div id="app">
<h1>性别:{{sex1}}</h1>
<!--sex的value是一个函数-->
<about :name="name1" :age="age1" :getSex="getSex"></about>
<br>
<about :name="name2" :age="age2"></about>
<br>
<about :name="name3" :age="age3"></about>
</div>
</template>
<script>
//引入组件
import about from './views/About'
export default {
data(){
return {
sex1:'',
name1:'孙悟空',
age1:66,
name2:'唐僧',
age2:88,
name3:'沙和尚',
age3:99,
}
},
methods:{
// 传递给子组件的函数
getSex(val){
//子组件调用这个函数,并传入形参。形参是就是子组件要传递过来的数据
console.log(val)
this.sex1 = val
}
},
//注册组件
components:{
about,
}
}
</script>
<style lang="scss">
</style>
子组件:
<template>
<div class="about">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{userAge}}</h2>
<button @click="addAge">++</button>
<br>
<button @click="sendSex">点击给父组件传递性别</button>
</div>
</template>
<script>
export default {
// getSex 父组件传递过来的函数
props:['name','age','getSex'],
data(){
return {
userAge:this.age,
sex:'男'
}
},
methods:{
addAge(){
this.userAge++
},
sendSex(){
//调用父组件传过来的函数,并把要传递的参数写在函数的参数中
this.getSex(this.sex)
}
}
}
</script>
第二种方式就是通过自定义事件来进行传递。
自定义方法来通信的步骤大概是这样的:首先在按钮上面创建一个点击事件,通过这个点击事件来向父组件发射一个自定义事件。它是通过$emit()来发射事件的。
$enit的第一个参数是自定义事件名,第二个参数是向父组件传递的参数。
子组件代码:
<template>
<div class="about">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{userAge}}</h2>
<button @click="addAge">++</button>
<br>
<button @click="sendSex">点击给父组件传递性别</button>
</div>
</template>
<script>
export default {
props:['name','age'],
data(){
return {
userAge:this.age,
sex:'男'
}
},
methods:{
addAge(){
this.userAge++
},
sendSex(){
//点击按钮,触发sendSex方法,利用$emit向父组件发射一个事件,$emit()第一个参数为事件名,第二个参数为要传递给父组件的值。
this.$emit('getSex',this.sex)
}
}
}
</script>
子组件通过$emit发射事件之后,父组件要接收。所以要在组件标签上面写一个自定义事件。这样当子组件使用$enit发射事件的时候,就会触发父组件里面这个自定义事件。
父组件代码:
<template>
<div id="app">
<h1>性别:{{sex1}}</h1>
<!--自定义一个事件,这个事件名是getSex(必须和子组件发射的事件名一样),-->
<!--当子组件$emit发射事件的时候,就会触发这个事件。触发这个事件就会调用addSex方法-->
<about :name="name2" :age="age2" @getSex="addSex"></about>
</div>
</template>
<script>
//引入组件
import about from './views/About'
export default {
data(){
return {
sex1:'',
name1:'孙悟空',
age1:66,
name2:'唐僧',
age2:88,
name3:'沙和尚',
age3:99,
}
},
methods:{
// 传递给子组件的函数
addSex(val){
//子组件触发自定义事件,调用这个函数,并传入形参。形参就是子组件要传递过来的数据
console.log(val)
this.sex1 = val
}
},
//注册组件
components:{
about,
}
}
</script>
<style lang="scss">
</style>
以上就是子父组件通信的使用方法。