资讯专栏INFORMATION COLUMN

vue非父子组件通信中eventbus被多次触发(vue中使用eventbus踩过的坑)

CHENGKANG / 3153人阅读

摘要:主要是看这是从上个页面传来的数据这一行数据的输出次数情况来判断事件触发次数。总结所以,如果想要用来进行页面组件之间的数据传递,需要注意亮点,组件事件应在生命周期内。其次,组件内的记得要销毁。

转载于简书 原文链接:https://www.jianshu.com/p/fde...

一开始的需求是这样子的,我为了实现两个页面组件之间的数据传递,假设我有页面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中就会理所当然的接受了数据。然而,结果却不如人意,看一下下面的动图。

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

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

所以,有两个问题。

问题:

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

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

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

// 我分别在页面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》")
 }

// 另外一个组件的我就不放出来了

测试结果图:

test.gif
image.png
其实,可以通过结果清楚看到,当我们还在页面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
      })
 },
接下来。看一下修改之后的效果

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

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

解决: 看一下github上提出的。issue https://github.com/vuejs/vue/...

image.png 尤大大提出了以下解决:

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

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

// 在B组件页面中添加以下语句,在组件beforeDestory的时候销毁。

  beforeDestroy () {
    bus.$off("get", this.myhandle)
  },
来看一下输出的结果

t可以看到,控制台第一次进去的时候就有输出,而且输出的不会逐次增加
*当然,尤大大还说可以写一个mixin?我还不知道是什么?以后在研究一下。

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

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

作者:Katherine的小世界 链接:https://www.jianshu.com/p/fde... 來源:简书

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94398.html

相关文章

  • vue数据传递--我有特殊的实现技巧

    摘要:同时有一种特殊的实现方案。组件之间传值有这么几种数据传递方式,和特殊的。在所有实例中使用其进行数据的通信。双多方使用同名事件进行沟通。数据非长效数据,无法保存,只在后生效。这样约定的好处是,我们能够记录所有中发生的改变。 前言 最近碰到了比较多的关于vue的eventBus的问题,之前定技术选型的时候也被问到了,vuex和eventBus的使用范围。所以简单的写一下。同时有一种特殊的实...

    xiaoxiaozi 评论0 收藏0
  • 整理4种Vue组件通信方式

    摘要:整理种组件通信方式重点是梳理了前两个父子组件通信和通信我觉得文档里的说明还是有一些简易我自己第一遍是没看明白。第四种通信方式利用比较复杂可以单独写一篇 整理4种Vue组件通信方式 重点是梳理了前两个,父子组件通信和eventBus通信,我觉得Vue文档里的说明还是有一些简易,我自己第一遍是没看明白。 父子组件的通信 非父子组件的eventBus通信 利用本地缓存实现组件通信 Vuex...

    MingjunYang 评论0 收藏0
  • vue8种组件通信方式, 值得收藏!

    摘要:一父组件通过的方式向子组件传递数据,而通过子组件可以向父组件通信。而且只读,不可被修改,所有修改都会失效并警告。 之前写了一篇关于vue面试总结的文章, 有不少网友提出组件之间通信方式还有很多, 这篇文章便是专门总结组件之间通信的 vue是数据驱动视图更新的框架, 所以对于vue来说组件间的数据通信非常重要,那么组件之间如何进行数据通信的呢?首先我们需要知道在vue中组件之间存在什么样...

    BicycleWarrior 评论0 收藏0
  • vue -- 父子组件传值,事件总线(eventbus)的使用方式

    摘要:我的个人博客地址资源地址非父子组件传值,事件总线的使用方式我的博客地址如果您对我的博客内容有疑惑或质疑的地方,请在下方评论区留言,或邮件给我,共同学习进步。 欢迎访问我的个人博客:http://www.xiaolongwu.cn 前言 先说一下什么是事件总线,其实就是订阅发布者模式; 比如有一个bus对象,这个对象上有两个方法,一个是on(监听,也就是订阅),一个是emit(触发,也就...

    zone 评论0 收藏0
  • 前端面试汇总VUE(二)

    摘要:采用了新旧的对比,获取差异的,最后一次性的更新到真实上。对基本属性进行监听对对象进行监听对对象某一个属性监听监听自定义指令全局指令,第一个参数是指令名,第二个参数是一个对象,对象内部有个的函数,函数里有这个参数,表示绑定了这个指令的元素。 11.vue 虚拟DOM的理解 Web界面由DOM树(树的意思是数据结构)来构建,当其中一部分发生变化时,其实就是对应某个DOM节点发生了变化,  ...

    Sanchi 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<