一、父子组件传值(props+$emit)
A)、父向子传值(props)
1、编写父组件基础代码
<template>
<div class="parent">
<h2>parent: </h2>
</div>
</template>
<script>
export default {
};
</script>
<style scoped lang='scss'>
.parent{
border: 1px solid red;
padding: 10px;
}
</style>
在views包下创建Parent.vue文件,并配置路由信息
展示效果
2、编写子组件基础代码
<template>
<div class="son1">
<h2>son1: </h2>
</div>
</template>
<script>
export default {
};
</script>
<style>
.son1{
border: 1px solid green;
padding: 10px;
margin: 10px;
}
</style>
在views包下创建son1.vue文件
在parent.vue中引入并使用
展示效果
3、使用
在父组件的data中添加值,并通过:绑定属性名和值(:name=“nickname”)
<template>
<div class="parent">
<h2>parent: </h2>
{{ nickname }}
<Son1 :name="nickname"></Son1>
</div>
</template>
<script>
import Son1 from '@/views/Son1.vue'
export default {
components:{
Son1
},
data() {
return {
nickname:'王晓斌'
}
},
};
</script>
<style scoped lang='scss'>
.parent{
border: 1px solid red;
padding: 10px;
}
</style>
在子组件中,通过props接值,并使用
展示效果:
B)、子向父传值($emit)
在子组件son1.vue中,添加一个按钮,并定一个方法,并在方法中通过$emit自定义一个事件(abc),并将值“王涛”放入
<template>
<div class="son1">
<h2>son1: </h2>
{{ name }}
<button @click="updatename">修改</button>
</div>
</template>
<script>
export default {
props:["name"],
methods:{
updatename(){
//自定义一个事件abc
this.$emit('abc', '王涛');
}
}
};
</script>
<style>
.son1{
border: 1px solid green;
padding: 10px;
margin: 10px;
}
</style>
在父组件parent.vue中,通过子组件中的自定义事件@abc,并绑定一个方法abc1111,将值获取并使用
<template>
<div class="parent">
<h2>parent: </h2>
{{ nickname }}
<Son1 :name="nickname" @abc="abc1111"></Son1>
</div>
</template>
<script>
import Son1 from '@/views/Son1.vue'
export default {
components:{
Son1
},
data() {
return {
nickname:'王晓斌'
}
},
methods: {
abc1111(e){
this.nickname = e;
}
},
};
</script>
<style scoped lang='scss'>
.parent{
border: 1px solid red;
padding: 10px;
}
</style>
二、祖孙组件传值(provide+inject)
A)、祖向孙传值(provide)
1、编写孙组件基础代码
在views包下创建gradeSon.vue文件
<template>
<div class="graderSon">
<h2>GrageSon: </h2>
</div>
</template>
<script>
export default {
};
</script>
<style scoped lang='scss'>
.graderSon{
border: 1px solid green;
margin: 10px;
padding: 10px;
}
</style>
在Son1.vue组件中引入并使用
<template>
<div class="son1">
<h2>son1: </h2>
{{ name }}
<button @click="updatename">修改</button>
<GradeSon></GradeSon>
</div>
</template>
<script>
import GradeSon from '@/views/GradeSon.vue'
export default {
props:["name"],
components:{
GradeSon
},
methods:{
updatename(){
//自定义一个事件abc
this.$emit('abc', '王涛');
}
}
};
</script>
<style>
.son1{
border: 1px solid green;
padding: 10px;
margin: 10px;
}
</style>
展示效果:
2、引出问题
在parent.vue中添加age属性
<template>
<div class="parent">
<h2>parent: </h2>
<div>姓名:{{ nickname }}</div>
<div>年龄:{{ age }}</div>
<Son1 :name="nickname" @abc="abc1111"></Son1>
</div>
</template>
<script>
import Son1 from '@/views/Son1.vue'
export default {
components:{
Son1
},
data() {
return {
nickname:'王晓斌',
age:18
}
},
methods: {
abc1111(e){
this.nickname = e;
}
},
};
</script>
<style scoped lang='scss'>
.parent{
border: 1px solid red;
padding: 10px;
}
</style>
展示效果:
问题:想让parent中的age值,在GrageSon组件内展示
3、解决办法一
使用props,将age从Parent.vue传到Son1.vue,再传到GrageSon.vue中
但是此方法不利于维护,麻烦
4、解决办法二(provide+inject)
依赖注入:https://cn.vuejs.org/v2/guide/components-edge-cases.html#%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5
使用provide,在parent中再加入一个数据对象job(为了演示)
具体办法
<template>
<div class="parent">
<h2>parent: </h2>
<div>姓名:{{ nickname }}</div>
<div>年龄:{{ age }}</div>
<div>工作:{{ job.type }}</div>
<Son1 :name="nickname" @abc="abc1111"></Son1>
</div>
</template>
<script>
import Son1 from '@/views/Son1.vue'
export default {
components:{
Son1
},
data() {
return {
nickname:'王晓斌',
age:18,
job:{
type:'java开发工程师'
}
}
},
//provide方法里面,设置依赖数据
provide:function(){
return {
job:this.job
}
},
methods: {
abc1111(e){
this.nickname = e;
}
},
};
</script>
<style scoped lang='scss'>
.parent{
border: 1px solid red;
padding: 10px;
}
</style>
在想使用job的子组件或者孙组件中使用inject
展示效果:
同理在GardeSon中进行上述操作
B)、孙修改值
因为job传过来的是job对象,相当于是传递过来job对象的地址,所以子组件修改后,所有的组件都会修改
三、兄弟组件传值($bus中央事件总线)
1、编写Son2.vue文件
<template>
<div class="son2">
<h2>Son2: </h2>
</div>
</template>
<script>
export default {
};
</script>
<style scoped lang='scss'>
.son2{
border: 1px solid orange;
margin: 10px;
padding: 10px;
}
</style>
展示效果:
2、编写Son1.vue文件
<template>
<div class="son1">
<h2>son1: </h2>
{{ name }}
<button @click="updatename">修改</button>
<div>工作:{{ job.type }}</div>
<div>
公司:{{ company.name }}
<br>
地址:{{ company.address }}
</div>
<GradeSon></GradeSon>
</div>
</template>
<script>
import GradeSon from '@/views/GradeSon.vue'
export default {
data() {
return {
company:{
name:"橡树软件",
address:"西安雁塔区"
}
};
},
props:["name"],
components:{
GradeSon
},
//注入父组件设施的依赖数据
inject:['job'],
methods:{
updatename(){
//自定义一个事件abc
this.$emit('abc', '王涛');
}
}
};
</script>
<style scoped lang='scss'>
.son1{
border: 1px solid green;
padding: 10px;
margin: 10px;
}
</style>
3、问题
将company相关信息传给Son展示
4、解决办法一
先传给parent,再传给son2,但是此方法过于繁琐,若碰到grageSon向son2传值的情况会更加复杂
5、解决办法二
$on:https://cn.vuejs.org/v2/api/#vm-on
依然使用$emit将值传出,再使用$on监听$emit定义的事件,但是此时面临一个问题为:在不同的组件中(如:son1和son2)的this.$emit和this.$on中的this不一致(this指自己当前的组件对象),所以在son2中通过this.$on监听不到son1中通过this.$emit所定义的事件因此,我们需要给vue的原型对象提供一个公共的对象,来存储事件,习惯使用$bus来命名因为这个公共的$bus需要包含$on和$emit,而vue的实例中包含,所以如下:
在main.js中:
//给vue的原型对象添加一个$bus属性,作为将来所有vue实例的中央事件总线
Vue.prototype.$bus = new Vue()
在son1.vue中
<template>
<div class="son1">
<h2>son1: </h2>
{{ name }}
<button @click="updatename">修改</button>
<div>工作:{{ job.type }}</div>
<div>
公司:{{ company.name }}
<br>
地址:{{ company.address }}
</div>
<button @click="toSon2">传给son2</button>
<GradeSon></GradeSon>
</div>
</template>
<script>
import GradeSon from '@/views/GradeSon.vue'
export default {
data() {
return {
company:{
name:"橡树软件",
address:"西安雁塔区"
}
};
},
props:["name"],
components:{
GradeSon
},
//注入父组件设施的依赖数据
inject:['job'],
methods:{
updatename(){
//自定义一个事件abc
this.$emit('abc', '王涛');
},
toSon2(){
this.$bus.$emit('toSon2',this.company)
}
}
};
</script>
<style scoped lang='scss'>
.son1{
border: 1px solid green;
padding: 10px;
margin: 10px;
}
</style>
在son2.vue中
<template>
<div class="son2">
<h2>Son2: </h2>
{{company}}
</div>
</template>
<script>
export default {
data() {
return {
company:{},
};
},
mounted() {
this.$bus.$on('toSon2',(e)=>{
console.log(e);
this.company = e;
})
},
};
</script>
<style scoped lang='scss'>
.son2{
border: 1px solid orange;
margin: 10px;
padding: 10px;
}
</style>