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 相关文章推荐
jQuery 白痴级入门教程
Nov 11 Javascript
javascript 鼠标悬浮图片显示原图 移出鼠标后原图消失(多图)
Dec 28 Javascript
模仿百度三维地图的js数据分享
May 12 Javascript
jQuery获取页面元素绝对与相对位置的方法
Jun 10 Javascript
用Axios Element实现全局的请求loading的方法
Mar 15 Javascript
JavaScript使用递归和循环实现阶乘的实例代码
Aug 28 Javascript
vue 之 css module的使用方法
Dec 04 Javascript
详解CommonJS和ES6模块循环加载处理的区别
Dec 26 Javascript
vue实现codemirror代码编辑器中的SQL代码格式化功能
Aug 27 Javascript
在Layui中操作数据表格,给指定单元格添加事件示例
Oct 26 Javascript
js实现无缝轮播图效果
Mar 09 Javascript
JavaScript 判断数据类型的4种方法
Sep 11 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
php常用的安全过滤函数集锦
2014/10/09 PHP
ThinkPHP实现更新数据实例详解(demo)
2016/06/29 PHP
php实现的中秋博饼游戏之掷骰子并输出结果功能详解
2017/11/06 PHP
laravel框架之数据库查出来的对象实现转化为数组
2019/10/23 PHP
Laravel jwt 多表(多用户端)验证隔离的实现
2019/12/18 PHP
javascript事件函数中获得事件源的两种不错方法
2014/03/17 Javascript
iPhone手机上搭建nodejs服务器步骤方法
2015/07/06 NodeJs
基于JavaScript实现图片点击弹出窗口而不是保存
2016/02/06 Javascript
jQuery实现图片轮播效果代码(基于jquery.pack.js插件)
2016/06/02 Javascript
原生js封装的一些jquery方法(详解)
2016/09/20 Javascript
Bootstrap 模态框(Modal)插件代码解析
2016/12/21 Javascript
详解js的六大数据类型
2016/12/27 Javascript
微信小程序 label 组件详解及简单实例
2017/01/10 Javascript
JavaScript数据结构之二叉树的计数算法示例
2017/04/13 Javascript
vue 下列表侧滑操作实例代码详解
2018/07/24 Javascript
vue实现移动端轻量日期组件不依赖第三方库的方法
2019/04/28 Javascript
JS学习笔记之数组去重实现方法小结
2019/05/29 Javascript
使用js在layui中实现上传图片压缩
2019/06/18 Javascript
Vue退出登录时清空缓存的实现
2019/11/12 Javascript
Element Backtop回到顶部的具体使用
2020/07/27 Javascript
[01:13]2015国际邀请赛线下观战现场
2015/08/08 DOTA
[01:11:35]Liquid vs LGD 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
python结合opencv实现人脸检测与跟踪
2015/06/08 Python
WIn10+Anaconda环境下安装PyTorch(避坑指南)
2019/01/30 Python
python网络爬虫 CrawlSpider使用详解
2019/09/27 Python
python实现树的深度优先遍历与广度优先遍历详解
2019/10/26 Python
实例讲解Python 迭代器与生成器
2020/07/08 Python
Python字符串及文本模式方法详解
2020/09/10 Python
Python截图并保存的具体实例
2021/01/14 Python
英国在线购买轮胎、预订汽车、汽车维修和装配网站:Protyre
2020/04/12 全球购物
幼儿园招生广告
2014/03/19 职场文书
团队队名口号大全
2014/06/06 职场文书
村党组织公开承诺书
2015/04/30 职场文书
酒店温馨提示语
2015/07/14 职场文书
爱国主义主题班会
2015/08/14 职场文书
我家女友可不止可爱呢 公开OP主题曲无字幕动画MV
2022/04/11 日漫