父子通信
1.父传子
父组件以属性的形式绑定值到子组件的身上,子组件通过porps接收。
porps 是单项绑定的,父组件的属性变化时,将传导给子组件,但反之则不会。
<template>
<div>
<p>父组件</p>
<Child :num="num"/>
<button @click="num++">+1</button>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
data(){
return{
num:0
}
},
components:{
Child
}
</script>
<template>
<div>
<p>子组件</p>
<p>{{ num }}</p>
</div>
</template>
<script>
export default {
//接收父组件的参数
props:['num']
}
</script>
在vue中,有一个实例属性也可以实现“父传子”的效果:$parent
我们可以在子组件中通过`this.$parent.xxx`获取父中的`xxx`数据的值,从而在子组件自身中去使用`xxx`的值。
但是需要注意,前面说的是父主动给数据给子,也就是父传子,而这里的$parent属于子去主动拿父的数据,语义上是两码事,但是效果一样。
2.父取子
父取子的数据信息。
(方向:子-父,但是区别于子传父,之前是主动,现在是被动)
ref
属性被用来给元素或子组件注册引用信息,引用信息将会注册在父组件的 $refs
对象上。如果在普通的 DOM 元素上使用ref
属性,则引用指向的就是 DOM 元素;如果ref
属性用在子组件上,引用就指向子组件实例。
-
ref
放在标签上,拿到的是原生节点。ref
放在组件上 拿到的是组件实例 -
原理:在父组件中通过
ref
属性(会被注册到父组件的$refs
对象上)拿到组件/DOM对象,从而得到组件/DOM中的所有的信息,也包括值)
<template>
<div>
<p>子组件</p>
<p>{{ count }}</p>
</div>
</template>
<script>
export default {
data(){
return{
count:0
}
},
methods:{
changeCount(){
this.count++
}
}
}
</script>
<template>
<div>
<p>父组件</p>
<Child ref="Child"/>
<button @click="changefun">触发子组件</button>
</div>
</template>
<script>
import Child from './Child'
export default {
components:{
Child
},
methods:{
//当前函数调用子组件中的函数 ref
changefun(){
console.log(this.$refs.Child.changeCount());
}
}
}
</script>
3.子传父
3.1子组件模板内容用$emit()触发自定义事件, $emit()方法至少有2个参数
- 第一个参数为自定义事件的名称
- 第二个参数为需要传递的数据(可以是任何格式的数据)
2.2 父组件模板内容中的子组件占位标签上用v-on或@ 绑定子组件自定的事件名,监听子组件的事件,实现通信。
<template>
<div>
<p>父组件</p>
<Child :arr="arr" @parentaddfun="addfun" />
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components:{
Child
},
methods:{
addfun(val){
this.arr.push(val)
}
},
data(){
return{
arr:['a','b','c']
}
}
}
</script>
<template>
<div>
<p>子组件</p>
<ul>
<li v-for="(item,index) in arr" :key="index">{{ item}}</li>
</ul>
<button @click="addfun"> 添加 </button>
</div>
</template>
<script>
export default {
props:['arr'],
methods:{
addfun(){
this.$emit('parentaddfun','子组件传往父组件一号')
}
}
}
</script>
事件总线通信(兄弟通信)
EventBus又被称之为中央事件总线
在Vue中通过单独的事件中心 来管理非父子关系组件即兄弟间的通信:
核心步骤:
创建一个全局的事件中心
//写一个js文件
import Vue from 'vue'
//1.用vue实例来做来事件中心的载体
export default new Vue()
写自定义事件
<template>
<div>
<p>子组件A</p>
<button @click="changefun"> 点击 </button>
</div>
</template>
<script>
import Bus from './Bus' //引入事件中心
export default {
methods:{
changefun(){
Bus.$emit('addfun','我是要传输的组件A一号')
}
}
}
</script>
<template>
<div>
<p>子组件B</p>
<!-- a 向 b 传输文件 自定义事件要写在b -->
</div>
</template>
<script>
import Bus from './Bus'
export default {
mounted(){
Bus.$on('addfun',this.addfn) //绑定自定义事件 (记得要写销毁)
},
beforeDestroy(){
Bus.$off('addfun',this.addfn)
},
methods:{
addfn(val){
console.log('我是组件B',val);
}
}
}
</script>
<template>
<div>
<P>父组件</P>
<ChildA />
<ChildB />
</div>
</template>
<script>
import ChildA from './ChildA.vue'
import ChildB from './ChildB.vue'
export default {
components:{
ChildA,
ChildB
}
}
</script>