中央事件总线传值及遇见的坑

中央事件总线

在vue项目中,各组件之间是需要传值的,有时候非父子关系的组件也需要通信。在简单的场景下,使用一个空的Vue实例作为中央事件总线。称为中央事件总线传值。

通过建立中间的事件bus总线。实现非父子组件之间的数据通信。

首先建立事件bus,我会新建一个bus.js文件;注册bus。
分别在组件中使用emit和on实现数据之间的通信;

bus.js
```

	//bus.js,注册Bus
	import Vue from 'vue'
	export default new Vue()
```
页面A发送方(组件emit触发事件)
```


	<template>
		 <div class="add-task" :class="{'ishide':isAdding}"  @click="addtask()">
		<i class="fa fa-plus-circle" aria-hidden="true"></i>
		添加任务
		</div>
	</template>
	<script>
	import Bus from '@/bus'
	export default {
	methods: {
	props: ['index'],
	data () {
 		return {
   			isAdding: false
 		}
	},
 	addtask () {
   	this.isAdding = true
   	Bus.$emit('adding-task', this.isAdding, this.index)  // 这里触发的事件是'adding-task',
   	传递了两个参数,分别是this.isAdding和this.index
   	this.$emit('addtask')
 			}
		}
	}

```
页面B接收方(on接收事件)
```

	// 模板中的代码就不展示了。
	主要展示的是script中的代码
	export default{
	data() //  这里的数据也不一一显示啦;
	created () {
	// 这里使用on监听了adding-task事件,接收到两个参数。所以一旦上面的组件中的adding-task事件触发,这里就会监听到。
	Bus.$on('adding-task', (state, index) => {
  		if (this.index === index) {
    		this.isShow = state
  		}
		})
		}
	}
```
中央事件总线的坑

当完成上述中央事件总线传值之后,就可以在接收方接收到正常的值,但是会存在一些问题:

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

所以,有两个问题。

问题:

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

第一次触发的时候页面B中的on事件没有被触发

产生原因

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

解决办法

我们可以把A页面组件中的emit事件写在beforeDestory中去。因为这个时候,B页面组件已经被created了,也就是我们写的 o n 事 件 已 经 触 发 了 , 所 以 可 以 在 b e f o r e D e s t o r y 的 时 候 , on事件已经触发了,所以可以在beforeDestory的时候, onbeforeDestoryemit事件

示例代码
```

	// 修改一下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
  		})
	},
```
问题二

后面再一次依次去触发的时候会出现,每一次都会发现好像之前的on事件分发都没有被撤销一样,导致每一次的事件触发执行越来越多。

产生原因

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

解决办法

在B组件页面中添加Bus.$off来关闭

######示例代码

```

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

```
总结

所以,如果想要用bus 来进行页面组件之间的数据传递,需要注意亮点,组件A e m i t 事 件 应 在 b e f o r e D e s t o r y 生 命 周 期 内 。 其 次 , 组 件 B 内 的 emit事件应在beforeDestory生命周期内。其次,组件B内的 emitbeforeDestoryBon记得要销毁

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值