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 相关文章推荐
js DOM 元素ID就是全局变量
Sep 20 Javascript
jQuery.validate 常用方法及需要注意的问题
Mar 20 Javascript
如何编写高质量JS代码
Dec 28 Javascript
js+jquery常用知识点汇总
Mar 03 Javascript
限制文本框只能输入数字||只能是数字和小数点||只能是整数和浮点数
May 27 Javascript
全面了解函数声明与函数表达式、变量提升
Aug 09 Javascript
JavaScript中Array的实用操作技巧分享
Sep 11 Javascript
jQuery的事件预绑定
Dec 05 Javascript
Mac系统下Webstorm快捷键整理大全
May 28 Javascript
JS兼容所有浏览器的DOMContentLoaded事件
Jan 12 Javascript
Bootstrap fileinput 上传新文件移除时触发服务器同步删除的配置
Oct 08 Javascript
微信小程序中限制激励式视频广告位显示次数(实现思路)
Dec 06 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 Smarty 字符比较代码
2011/02/27 PHP
php学习笔记(三)操作符与控制结构
2011/08/06 PHP
关于php 高并发解决的一点思路
2017/04/16 PHP
PHP通过GD库实现验证码功能示例
2019/02/23 PHP
jquery 防止表单重复提交代码
2010/01/21 Javascript
javascript 用原型继承来实现对象系统
2010/03/22 Javascript
js各种验证文本框输入格式(正则表达式)
2010/10/22 Javascript
jQuery cdn使用介绍
2013/05/08 Javascript
Javascript事件实例详解
2013/11/06 Javascript
深入分析node.js的异步API和其局限性
2016/09/05 Javascript
AngularJS中$http使用的简单介绍
2017/03/17 Javascript
vue-cli之router基本使用方法详解
2017/10/17 Javascript
基于vue2实现上拉加载功能
2017/11/28 Javascript
Vue.js中关于侦听器(watch)的高级用法示例
2018/05/02 Javascript
关于js对textarea换行符的处理方法浅析
2018/08/03 Javascript
jQuery实现获取及设置CSS样式操作详解
2018/09/05 jQuery
Vue2.x中利用@font-size引入字体图标报错的解决方法
2018/09/28 Javascript
JS实现百度搜索框关键字推荐
2020/02/17 Javascript
使用Angular9和TypeScript开发RPG游戏的方法
2020/03/25 Javascript
一篇文章让你搞懂JavaScript 原型和原型链
2020/11/23 Javascript
[03:49]DOTA2 2015国际邀请赛中国区预选赛第二日现场百态
2015/05/27 DOTA
Python基本数据结构与用法详解【列表、元组、集合、字典】
2019/03/23 Python
Django 配置多站点多域名的实现步骤
2019/05/17 Python
Python测试线程应用程序过程解析
2019/12/31 Python
pytorch实现保证每次运行使用的随机数都相同
2020/02/20 Python
Python PyQt5整理介绍
2020/04/01 Python
Python基于百度AI实现OCR文字识别
2020/04/02 Python
德国专业木制品经销商:Holz-Direkt24
2019/12/26 全球购物
澳大利亚宠物食品和用品商店:PETstock
2020/01/02 全球购物
二年级小学生评语
2014/04/21 职场文书
派出所所长先进事迹
2014/05/19 职场文书
绿色环保标语
2014/06/12 职场文书
离婚案件上诉状
2015/05/23 职场文书
2015暑假假期总结
2015/07/13 职场文书
卫生主题班会
2015/08/14 职场文书
Python将CSV文件转化为HTML文件的操作方法
2021/06/30 Python