在之前我们只用过父传子,子传父进行传数据,这时候当组件嵌套比较深或比较复杂的情况,这时候就用到了事件总线 (EventBus) 

如何理解事件总线呢,你可以理解为用来传输数据的一条线

注意点:有组件发布事件后 剩余的所有组件都可以进行监听事件

一、使用EventBus

1. 创建事件总线   main.js

import Vue from 'vue'
// 创建事件总线   就相当于创建了一个新的vue实例
const bus = new Vue()
// 把bus挂载到了Vue的原型上, 保证所有的组件都能通过 this.$bus访问到事件总线
Vue.prototype.$bus = bus

2. 页面使用 发布事件 - 传递值

// this.$bus.$emit('事件名', 额外参数)
this.$bus.$emit('send', 'hello')

3.订阅事件 - 接收组件值

// 1. 在created中订阅
// 2. 回调函数需要写成箭头函数
// this.$bus.$on('事件名', 事件回调函数)
this.$bus.$on('send', msg => {console.log(msg)
})

二、注意点

$on先执行 在执行$emit触发事件  (嵌套关系)

知道此问题必须先要知道父子级组件嵌套关系的钩子函数执行顺序?如果你对生命周期钩子函数不了解先来看 生命周期的详解

父子嵌套生命周期  会先执行父组件中的前三个后 执行子组件的前三个 再去执行父组件的mounted

接下俩我们做个实验 看看为什么先执行$on 在执行$emit

父组件中

<template><div><son></son></div>
</template>
<script>
import son from './Son.vue'
export default {components: {son},created() {console.log('父组件:我被创建啦')this.$bus.$emit('bus', 10)}
}
</script>

子组件

<template><div>{{message}}</div>
</template><script>
export default {data () {return {message: ''}},created () {console.log('子组件:我被创建啦')this.$bus.$on('bus', (val) => {console.log(val)this.message = val})},
}
</script>

这时候是看不见任何接收信息的  

原因就是 没有等子组件$on去注册事件后就执行了父组件$emit 所以接收不到信息

解决方法:把父组件中的$emit事件放在mounted钩子函数中 等待子组件创建并注册$on事件后再去触发$emit。 只适合嵌套关系 可能出现兄弟关系 也要看情况进行使用

  mounted () {console.log('父组件:mounted')this.$bus.$emit('bus', 10)}

三、移除事件监听

来看个栗子

父组件中没两秒进行一次传递  点击v-if后将子组件进行 销毁或重新创建

<template><button @click="isShow=!isShow"> {{isShow?'销毁':'重建'}}  </button><son v-if="isShow=isShow">son</son></div>
</template>
<script>
import son from './Son.vue'
export default {components: {son},data () {return {isShow: true}},created () {console.log('父组件:我被创建啦')setInterval(() => {this.$bus.$emit('bus', 10)}, 2000)}
}

子组件 

<template><div>{{message}}</div>
</template><script>
export default {data () {return {message: null}},created () {console.log('子组件:我被创建啦')this.$bus.$on('bus', (val) => {console.log(val)this.message = val})}
}
</script>

问题点:当点击销毁子组件的时候 子组件还能接收到数据吗?对应的回调函数还能在执行吗? 答案是 会,事件订阅功能是$eventBus对象完成的,与组件无关,当你点击销毁后 再点击创建又会多了一个订阅事件,依次类推每次点击新建后都会多一个订阅事件

造成原因:事件订阅是通过$eventBus对象完成的 与组件无关

如果不移除事件监听 并且会造成内存泄漏

在son组件中修改

  created () {console.log('子组件:我被创建啦')const m = 1 * 1024 * 1024const arr = new Array(m).fill('a')this.$bus.$on('bus', function f1 (val) {// 注意这里有一个闭包console.log(val, 'son listen... bus', arr[1])})},

通过v-if 销毁和重新创建来看通过数据发现 销毁后并没有对空间进行释放

解决方案: 在子组件销毁后进行取消订阅事件

  destroyed () {// 取消对bus事件的监听this.$bus.$off('bus')}

对bus取消事件监听后  内存得到了释放

总结:

1. 任何组件都可以在事件总线中发布事件 this.$bus.$emit('xxx','传递参数') 

2. 任何组件都可以在事件总线中监听事件 this.$bus.$on('xxx',(接收参数)=>{ 对形参进行操作 }) 

3. main.js注册空的Vue对象, 只负责$on注册事件, $emit触发事件, 一定要确保​$on先执行

4.$off的格式:

  • $off() 会取消所有的事件订阅;

  • $off('事件名') 会取消指定事件名的;

  • $off('事件名', 回调) 会取消指定事件名的,指定回调

参考 凡人进阶

Vue事件总线(EventBus)、$on、$emit、$off相关推荐

  1. vue 事件总线EventBus的概念、使用以及注意点

    vue组件中的数据传递最最常见的就是父子组件之间的传递.父传子通过props向下传递数据给子组件:子传父通过$emit发送事件,并携带数据给父组件.而有时两个组件之间毫无关系,或者他们之间的结构复杂, ...

  2. vue事件总线_[面试] 聊聊你对 Vue.js 框架的理解

    作者:yacan8 https://github.com/yacan8/blog/issues/26 本文为一次前端技术分享的演讲稿,所以尽力不贴 Vue.js 的源码,因为贴代码在实际分享中,比较枯 ...

  3. Android事件总线——EventBus的使用

    前言 首先我们来说下事件总线,它的作用:为了更简化并更高质量的在Activity,Fragment,Thread和Service等之间的通信,解决组件之间高耦合的同时仍能进行高效的通信. 什么是Eve ...

  4. 自己动手写事件总线(EventBus)

    2019独角兽企业重金招聘Python工程师标准>>> 本文由云+社区发表 事件总线核心逻辑的实现. <!--more--> EventBus的作用 Android中存在 ...

  5. 手写实现简单的Vue事件总线

    一.什么是事件总线 自定义事件总线属于一种观察者模式,其中包括三个角色: 发布者(Publisher):发出事件(Event): 订阅者(Subscriber):订阅事件(Event),并且会进行响应 ...

  6. 基于Kotlin ShareFlow封装事件总线EventBus

    经过高强度测试,(基本上)莫得问题 需要导入的kotlin协程库: //lifecycleScope(这里是用kotlin写的) api("androidx.activity:activit ...

  7. 「后端小伙伴来学前端了」Vue中全局事件总线(GlobalEventBus)原理及探究过程

    前言 上一篇文章写了 Vue 中的自定义事件,自定义事件是全局事件总线基础.我在上一篇文章中埋下了一个小小的伏笔.如下图: 我说过,在Vue中如果我们用(@orv-on)给组件绑定上一个自定义事件,其 ...

  8. 「后端小伙伴来学前端了」Vue中利用全局事件总线实现组件之间通信

    月亮啊月亮 你能照见南边,也能照见北边 照见她,你跟她说一声,就说我想她了. 前言 前一篇文章写了 vue 中利用 Props 实现组件之间的通信,那种方式是最简单也是最基础的组件之间的通信方式.父组 ...

  9. [Vue源码分析]自定义事件原理及事件总线的实现

    最近小组有个关于vue源码分析的分享会,提前准备一下- 前言: 我们都知道Vue中父组件可以通过 props 向下传数据给子组件:子组件可以通过向$emit触发一个事件,在父组件中执行回调函数,从而实 ...

最新文章

  1. Lumen框架多数据库连接配置方法
  2. 【廖雪峰python入门笔记】变量
  3. linux C实现mkdir功能
  4. 【Linux】- 获取root权限命令
  5. 一些sql 语句(行列转换等)
  6. python字符串赋值与java区别_java和python细节总结和java中string 的+操作
  7. IE与Firefox的CSS兼容大全~~论坛推荐~!!!
  8. 利用维纳滤波编码实现给定的运动模糊图像恢复
  9. 【渝粤教育】广东开放大学 社会学概论 形成性考核 (50)
  10. Jhipster创建微服务【0】——踩坑
  11. 怎么把activeform生成的相关的js全给删除 版本yii2.0+[证实可行]
  12. Tomcat是怎么工作的(1) -- 开篇
  13. Element UI 中国省市区级联数据js
  14. 2022年贵州省职业院校技能大赛中职组网络安全赛项规程
  15. 活前缀及构造活前缀的DFA
  16. redit mysql_【Voten】基于Laravel实现的类似Reddit的实时社交论坛系统
  17. matlab火箭升空,火箭升空原理
  18. Oracle 版本查看及版本号说明
  19. 亚马逊长尾关键词是什么?亚马逊长尾关键词优势
  20. 4G Cat.1跟通常我们说的4G有什么区别

热门文章

  1. 如何全面展现运维生态状况
  2. WPS Office 2019 for Linux来了
  3. Postgresql Automatic Vacuuming
  4. 非一般的原因:Unable instantiate application xxx.MyApplication: java.lang.ClassNotFoundException
  5. 牛客网[编程题] DNA合成(Java实现)
  6. MogaFX外汇储备以一年多来的最快速度增长
  7. 【机器学习】KNN算法及其用KNN解决字体反爬
  8. 企业招标采购(系统)降本增效的20个措施
  9. 2014秋C++ 第8周项目 分支程序设计
  10. 切换分支后项目启动不了