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 相关文章推荐
验证javascript中Object和Function的关系的三段简单代码
Jun 27 Javascript
js获取系统的根路径实现介绍
Sep 08 Javascript
javascript设计模式之解释器模式详解
Jun 05 Javascript
JQuery实现左右滚动菜单特效
Sep 28 Javascript
jQuery Mobile弹出窗、弹出层知识汇总
Jan 05 Javascript
js原生代码实现轮播图的实例讲解
Jul 28 Javascript
JS实现的简单分页功能示例
Aug 23 Javascript
详解vuex commit保存数据技巧
Dec 25 Javascript
详解javascript 变量提升(Hoisting)
Mar 12 Javascript
VUE实现Studio管理后台之鼠标拖放改变窗口大小
Mar 04 Javascript
vue.js实现照片放大功能
Jun 23 Javascript
测量JavaScript函数的性能各种方式对比
Apr 27 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
php4与php5的区别小结(配置异同)
2011/12/20 PHP
PHP中的Streams详细介绍
2014/11/12 PHP
微信自定义菜单的创建/查询/取消php示例代码
2016/08/05 PHP
laravel框架中间件 except 和 only 的用法示例
2019/07/12 PHP
jQuery ajax在GBK编码下表单提交终极解决方案(非二次编码方法)
2010/10/20 Javascript
鼠标拖动实现DIV排序示例代码
2013/10/14 Javascript
jquery果冻抖动效果实现方法
2015/01/15 Javascript
JavaScript模拟深蓝vs卡斯帕罗夫的国际象棋对局示例
2015/04/22 Javascript
Javascript编写2048小游戏
2015/07/07 Javascript
html+js实现简单的计算器代码(加减乘除)
2016/07/12 Javascript
javascript中对象的定义、使用以及对象和原型链操作小结
2016/12/14 Javascript
jQuery使用正则表达式替换dom元素标签用法示例
2017/01/16 Javascript
JavaScript评论点赞功能的实现方法
2017/03/13 Javascript
vue项目使用微信公众号支付总结及遇到的坑
2018/10/23 Javascript
[04:49]2014DOTA2国际邀请赛 Newbee顺利挺进总决赛 ImbaTV独家专访
2014/07/19 DOTA
python数据类型_元组、字典常用操作方法(介绍)
2017/05/30 Python
Python中交换两个元素的实现方法
2018/06/29 Python
django的ORM操作 删除和编辑实现详解
2019/07/24 Python
Python读取分割压缩TXT文本文件实例
2020/02/14 Python
python 如何调用 dubbo 接口
2020/09/24 Python
10张动图学会python循环与递归问题
2021/02/06 Python
html5 touch事件实现触屏页面上下滑动(一)
2016/03/10 HTML / CSS
UNIX文件名称有什么规定
2013/03/25 面试题
门卫工作岗位职责
2013/12/17 职场文书
求职信模板标准格式范文
2014/02/23 职场文书
劳动工资科岗位职责范本
2014/03/02 职场文书
警校毕业生自我评价
2014/04/06 职场文书
小学班长竞选演讲稿
2014/04/24 职场文书
装修施工安全责任书
2014/07/24 职场文书
学生安全责任书范本
2014/07/24 职场文书
团员自我评价范文
2015/03/10 职场文书
开展警示教育活动总结
2015/05/09 职场文书
创业计划书之物流运送
2019/09/17 职场文书
小程序实现文字循环滚动动画
2021/06/14 Javascript
MySQL系列之十 MySQL事务隔离实现并发控制
2021/07/02 MySQL
python Tkinter模块使用方法详解
2022/04/07 Python