vue中eventbus被多次触发以及踩过的坑


Posted in Javascript onDecember 02, 2017

一开始的需求是这样子的,我为了实现两个页面组件之间的数据传递,假设我有页面A,点击页面A上的某一个按钮之后,页面会自动跳转到页面B,同时我希望将页面A上的某一些参数携带过去给页面B。(我知道,小参数的时候可以通过路由的params或者query去传参数,或者大型数据可以用vuex来处理,很遗憾我到现在还没有做很大型的项目,所以还没有用过vuex,接下来会学习一下。)

然后我就想,这不就是不同组件之间的数据传递问题而已吗?直接用bus 巴士事件来传递数据不就行了吗。于是,我就很愉快地进行了。关于vue中的eventbus的使用,我之前在一篇vue中的数据传递中有提到过。

先给你们看一下我一开始的代码:

实现目标:

点击之后,bus emit事件,然后顺便跳转路由到/moneyRecord页面。

接下来就是在MoneyRecord页面中去on接收这个事件,然后接受参数。

// 这是页面A的内部触发bus事件的代码
 editList (index, date, item) {
// 点击进入编辑的页面,需要传递的参数比较多。
  console.log(index, date, item)
  bus.$emit('get', {
  item: item.type,
  date: date
  })
  this.$router.replace({path: '/moneyRecord'})
 }

// moneyRecord页面
created () {
 //这里我将icon的list给保存下来了
 bus.$on('get', this.myhandle)
 },
methods: {
 myhandle (val) {
  console.log(val, '这是从上个页面传递过来的参数')
 }
}

就当我欣喜若狂的时候,觉得自己只要在页面A触发了get事件,页面B中就会理所当然的接受了数据。然而,结果却不如人意,看一下下面的动图。

主要是看“”这是从上个页面传来的数据这一行数据的输出次数情况来判断事件触发次数。“”

vue中eventbus被多次触发以及踩过的坑

不知道你有没有发现,就是我第一次进去list页面的时候,我随便点击一下list下的任何一个item,控制台没有输出。但是当我第二次再点击触发事件的时候,就会输出一个测试数据。再一次进去点击,就输出两个数据。。。依次增加了。(控制台上那个“这是从上个页面传来的数据”就是测试数据)

所以,有两个问题。

问题:

  1. 问题1: 为什么第一次触发的时候页面B中的on事件没有被触发
  2. 问题2: 为什么后面再一次依次去触发的时候会出现,每一次都会发现好像之前的on事件分发都没有被撤销一样,导致每一次的事件触发执行越来越多。

解决

针对问题1

这个还得从vue的生命周期说起了,我先进行了测试,就是当从页面组件A跳转到页面组件B的时候,两个组件的生命周期分别是怎么样的,关于vue的生命周期具体每一个时期做什么事情我就不再赘述了,下面po一张vue生命周期的图。

vue中eventbus被多次触发以及踩过的坑

我自己做了实验来验证,这个页面跳转过程中,这两个组件的生命周期的执行情况。

// 我分别在页面A和页面B中去添加以下代码:
beforeCreate () {
 console.group('%c%s', 'color:red', 'beforeCreate 创建前状态===============组件2》')
 },
 created () {
 console.group('%c%s', 'color:red', 'created 创建完毕状态===============组件2》')
 },
 beforeMount () {
 console.group('%c%s', 'color:red', 'beforeMount 挂载前状态===============组件2》')
 },
 mounted () {
 console.group('%c%s', 'color:red', 'mounted 挂载状态===============组件2》')
 },
 beforeUpdate () {
 console.group('%c%s', 'color:red', 'beforeUpdate 更新前状态===============组件2》')
 },
 updated () {
 console.group('%c%s', 'color:red', 'updated 更新状态===============组件2》')
 },
 beforeDestroy () {
 console.group('%c%s', 'color:red', 'beforeDestroy 破前状态===============组件2》')
 },
 destroyed () {
 console.group('%c%s', 'color:red', 'destroyed 破坏状态===============组件2》')
 }
// 另外一个组件的我就不放出来了

测试结果图:

vue中eventbus被多次触发以及踩过的坑

vue中eventbus被多次触发以及踩过的坑

其实,可以通过结果清楚看到,当我们还在页面A的时候,页面B还没生成,也就是页面B中的 created中所监听的来自于A中的事件还没有被触发。这个时候当你A中emit事件的时候,B其实是没有监听到的。

再看一下,红色的是B页面组件,当你从页面A到页面B跳转的时候,发生了什么?首先是先B组件先created然后beforeMount接着A组件才被销毁,A组件才执行beforeDestory,以及destoryed.

所以,我们可以把A页面组件中的emit事件写在beforeDestory中去。因为这个时候,B页面组件已经被created了,也就是我们写的$on事件已经触发了

所以可以,在beforeDestory的时候,$emit事件。

// 修改一下A页面中的代码:
// 这是原先的代码
 editList (index, date, item) {
// 点击进入编辑的页面,需要传递的参数比较多。
  console.log(index, date, item)
  this.item = item.type
  this.date = date
  this.$router.replace({path: '/moneyRecord'})
 }
// 重新在data属性内部定义新的变量,来存储要传过去的数据;
然后:
 beforeDestroy () {
 console.log(this.highlight, '这是今年的数据', this, '看看组件销毁之前会发生什么')
 bus.$emit('get', {
  item: this.item,
  date: this.date
  })
 },

接下来。看一下修改之后的效果

vue中eventbus被多次触发以及踩过的坑

可以看到,就是第一次点击list的时候,也就是第一次触发emit事件的时候,控制太就输出了,所以在beforeDestoryed去$emit是起到作用的,B页面组件也监听$on到了。

但是,好像,就是事件的触发还是会依次增加,就是控制台的输出每次都有所增加了。。。

解决:

看一下github上提出的。https://github.com/vuejs/vue/issues/3399

vue中eventbus被多次触发以及踩过的坑

尤大大提出了以下解决:

vue中eventbus被多次触发以及踩过的坑

*就是说,这个$on事件是不会自动清楚销毁的,需要我们手动来销毁。(不过我不太清楚这里的external bus 是什么意思,有大神能解答一下的吗,尤大大也提到如果是注册的是external bus 的时候需要清除)****

所以。我在B组件页面中添加Bus.$off来关闭。代码如下:

// 在B组件页面中添加以下语句,在组件beforeDestory的时候销毁。
 beforeDestroy () {
 bus.$off('get', this.myhandle)
 },

来看一下输出的结果

vue中eventbus被多次触发以及踩过的坑

t可以看到,控制台第一次进去的时候就有输出,而且输出的不会逐次增加

*当然,尤大大还说可以写一个mixin?我还不知道是什么?以后在研究一下。

总结: 所以,如果想要用bus 来进行页面组件之间的数据传递,需要注意亮点,组件A$emit事件应在beforeDestory生命周期内。其次,组件B内的$on记得要销毁。

提问时间:你们在实现页面组件之间的数据传递有什么好的方法吗?可以留言分享一下吗?有时候虽然也可以通过从后台获取,但是考虑到数据只有几个需要传的话,就没有必要去请求数据,我知道有的还有用vueX传递。还有呢?

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Google韩国首页图标动画效果
Aug 26 Javascript
JObj预览一个JS的框架
Mar 13 Javascript
使用ExtJS技术实现的拖动树结点
Aug 05 Javascript
jquery实现经典的淡入淡出选项卡效果代码
Sep 22 Javascript
js中获取时间new Date()的全面介绍
Jun 20 Javascript
Angular ng-class详解及实例代码
Sep 19 Javascript
jQuery+json实现动态创建复杂表格table的方法
Oct 25 Javascript
bootstrap datetimepicker日期插件使用方法
Jan 13 Javascript
vue.js模仿京东省市区三级联动的选择组件实例代码
Nov 22 Javascript
JavaScript中set与get方法用法示例
Aug 15 Javascript
vue在index.html中引入静态文件不生效问题及解决方法
Apr 29 Javascript
vue集成chart.js的实现方法
Aug 20 Javascript
Angular之toDoList的实现代码示例
Dec 02 #Javascript
React Native 使用Fetch发送网络请求的示例代码
Dec 02 #Javascript
vue微信分享 vue实现当前页面分享其他页面
Dec 02 #Javascript
Vue按需加载的具体实现
Dec 02 #Javascript
使用Vue完成一个简单的todolist的方法
Dec 01 #Javascript
将jquery.qqFace.js表情转换成微信的字符码
Dec 01 #jQuery
如何让你的JS代码更好看易读
Dec 01 #Javascript
You might like
利用文件属性结合Session实现在线人数统计
2006/10/09 PHP
php中获取关键词及所属来源搜索引擎名称的代码
2011/02/15 PHP
CI使用Tank Auth转移数据库导致密码用户错误的解决办法
2014/06/12 PHP
php使用pdo连接并查询sql数据库的方法
2014/12/24 PHP
php实现批量上传数据到数据库(.csv格式)的案例
2017/06/18 PHP
JavaScript For Beginners(转载)
2007/01/05 Javascript
从零开始学习jQuery (八) 插播:jQuery实施方案
2011/02/23 Javascript
javascript 学习笔记(六)浏览器类型及版本信息检测代码
2011/04/08 Javascript
jquery解析xml字符串简单示例
2014/04/11 Javascript
判断复选框是否被选中的两种方法
2014/06/04 Javascript
函数式 JavaScript(一)简介
2014/07/07 Javascript
jQuery中:enabled选择器用法实例
2015/01/04 Javascript
jQuery基于函数重载实现自定义Alert函数样式的方法
2016/07/27 Javascript
JavaScript中子对象访问父对象的方式详解
2016/09/01 Javascript
基于js中的原型(全面讲解)
2017/09/19 Javascript
实现两个文本框同时输入的实例
2017/09/25 Javascript
JS实现获取毫秒值及转换成年月日时分秒的方法
2018/08/15 Javascript
Vue实现远程获取路由与页面刷新导致404错误的解决
2019/01/31 Javascript
JS实现查找数组中对象的属性值是否存在示例
2019/05/24 Javascript
[03:22]DAC最前线(第二期)—DOTA2亚洲邀请赛主赛场周边及线路探访
2015/01/24 DOTA
[02:17]《辉夜杯》TRG战队巡礼
2015/10/26 DOTA
利用Python自动监控网站并发送邮件告警的方法
2016/08/24 Python
详解python的webrtc库实现语音端点检测
2017/05/31 Python
对Python中9种生成新对象的方法总结
2018/05/23 Python
python 在屏幕上逐字显示一行字的实例
2018/12/24 Python
美国网上鞋城:Shoeline.com
2016/11/17 全球购物
英国评分最高的女性剃须刀订阅盒:FFS Beauty
2018/01/25 全球购物
Reebok官方旗舰店:美国知名健身品牌锐步
2019/01/07 全球购物
澳大利亚领先的武术用品和健身器材供应商:SMAI
2019/03/24 全球购物
本科生个人求职自荐信
2013/09/26 职场文书
《孙权劝学》教学反思
2014/04/23 职场文书
说明书范文
2014/05/07 职场文书
介绍信如何写
2015/01/31 职场文书
垂直极限观后感
2015/06/08 职场文书
WordPress多语言翻译插件 - WPML使用教程
2021/04/01 PHP
OpenCV绘制圆端矩形的示例代码
2021/08/30 Python