在vue项目中了解组件间通讯很重要,也是最基础的面试题,可以大致总结为以下几种情况和方法:
一、父向子传值父 to 子 :通过动态绑定属性的方式,子组件在props中去接收,占为已用
// father.vue <child :name="name" /> data() { return { name:'Echoyya', } } // child.vue export default { props: ['name'], mounted() { console.log(this.name) // Echoyya } } 二、子向父传值 - 1. 事件分发 emit子 to 父 :通过.emit('事件名称', 传递的参数)事件分发的方式, 父组件当中,调用子组件标签上绑定自定义事件,其中包含一个参数,即子组件传递过来的数据
emit 只能接受两个参数,其余不生效,第一个参数:事件名称,第二个: 传递的数据
事件分发,不一定要通过点击事件,也可使用钩子函数等
需要传递多个参数时,emit第二个参数可选择数组或是对象
// father.vue <child @send="getChildData" /> methods: { getChildData(data){ console.log('子组件传递过来的数据:' + data); } } // child.vue <button @click="send">发送数据</button> export default { data() { return { year:2021 }; }, methods:{ send(){ this.$emit('send',this.year) } } }; 三、子向父传值 - 2. 父组件动态绑定方法
除了平时常见的emit 事件分发的方式实现子向父传值,还有一种不太常见的方式
在前面有提到过,父向子传值可以通过在标签上动态绑定属性的方式,同样也可以动态绑定方法,在子组件props中接收
在根据实际情况,在子组件中调用该方法,并传值,此时父组件执行对应的方法及参数的处理,该参数便是子向父传递的数据
// father.vue <child :fn="getChildData" /> methods: { getChildData(data){ // 子组件传递过来的数据 console.log(data); // 子组件 - 2021 } } // child.vue export default { props: ['fn'], mounted(){ this.fn('子组件 - 2021') } }; 四、(主动)父组件主动获取子组件的数据和方法
父组件中调用子组件,绑定一个ref属性
主动获取属性:this.$refs.ref名称.属性
主动调用方法:this.$refs.ref名称.方法()
// father.vue <child :name="name" ref="child" /> mounted() { console.log(this.$refs.child.year); // 2021 this.$refs.child.showName() // Echoyya:2021 } // child.vue export default { data(){ return { year:2021 } }, methods:{ showName(){ console.log('Echoyya:'+ this.year); } } }; 五、(主动)子组件主动获取父组件的数据和方法
子组件中调用父组件,使用 this.$parent
主动获取属性:this.$parent.属性
主动调用方法:this.$parent.方法(),还可以向父组件传递参数
// father.vue <div> <child /> </div> <script> import child from "./components/child"; export default { components: { child }, data() { return { name:'Echoyya', }; }, methods: { parentMethod(data){ // 可以接收子组件调用时传递的参数 console.log(data); // 2021 } } }; </script> // child.vue export default { mounted(){ console.log(this.$parent.name); // Echoyya this.$parent.parentMethod(2021); // 2021 } }; 六、EventBus 传值多层级组件之间相互传值,或兄弟组件之间传值,通常使用EventBus,实际上就是 vm,即 Vue 的实例,通过发布订阅者模式,实现任意两组件之间的通讯,父子亦可。
首先创建EventBus文件,导出vm 实例
在需要通讯的两组件中分别引入该文件
通过发布订阅 .$emit 和 .$on 实现传值 ,操作的事件名需相同。
// EventBus.js import Vue from 'vue' var vm = new Vue() export default vm // App.vue <template> <div> <bus-one /> <bus-two /> </div> </template> <script> import busOne from "./components/bus1"; import busTwo from "./components/bus2"; export default { components: { busOne, busTwo } } </script> // bus1.vue <template> <div> 组件 1 发布 <button @click="sendNum">通讯发送数据</button> </div> </template> <script> import eb from "../EventBus"; export default { methods:{ sendNum(){ eb.$emit('sendData',111) } } }; </script> // bus2.vue <template> <div> 组件 2 订阅 </div> </template> <script> import eb from "../EventBus"; export default { created(){ eb.$on('sendData',function(data){ console.log(data); // 111 }) } }; </script> EventBus 内部实现原理
手动模拟一个 EventBus,实现发布订阅的效果,创建一个 myEventBus 文件
创建一个对象,分别设置发布、订阅的事件,以及事件存储的对象,通过事件订阅将事件存储至事件对象中,
事件发布时,自动调用事件对象中相同 key 的所有事件