vue中eventBus解决兄弟组件调用问题

前端 · 2020-01-19 ·

vue中父子组件通信是使用频率较多的场景,通过"props down , events up"我们就简单的实现了父子组件之间的双向传值,这是很基本的知识点,那么问题来了,非父子组件如何通信呢?eventBus就是用来解决非父子组件的通信。

中央事件总线eventBus的实质就是创建一个vue实例,通过一个空的vue实例作为桥梁实现vue组件间的通信。它是实现非父子组件通信的一种解决方案。事件总线,这个概念一看不好理解,它实质就是let eventBus = new Vue(),利用vue的$on响应事件,$emit触发事件,然后需要通信的2个组件都引用eventBus,进而达到跨组件传递信息的目的。

1.首先定义一个公共的eventBus.js

//eventBus.js
import Vue from 'vue';
export const EventBus=new Vue();

2.我们在兄弟组件BrotherA 组件中引用eventBus.js,并用$on去响应事件

<!--BrotherA-->
<template>
    <div>
        <p>BrotherA 组件</p>
        <p>内容:{{num}}</p>
    </div>
</template>
<script>
import { eventBus } from '../eventBus.js'
export default {
    name: 'BrotherA',
    data() {
        return {
            num: 1
        }
    },
    created() {
        eventBus.$on('add',()=>{
            this.num++
        });
    },
    beforeDestroy() {
        eventBus.$off('add');
    }
}
</script>

但是到这儿后,一定要注意一个最容易忽视,又必然不能忘记的东西,那就是清除事件总线eventBus。

不手动清除,它是一直会存在的,这样的话,缓存越来越大,因为事件操作的数据无法释放,对于数据量大的组件,可能会导致内存泄露!所以需要及时手动清除。

3.我们在兄弟组件BrotherB 组件中引用eventBus.js,并用$emit去触发事件

<!--BrotherB-->
<template>
    <div>
        <p>BrotherB 组件</p>
        <button @click='add()'>增加</button>
    </div>
</template>
<script>
import { eventBus } from '../eventBus.js'
export default {
    name: 'BrotherB',
    methods: {
        add() {
            eventBus.$emit('add')
        }
    }
}
</script>

4.兄弟组件BrotherA和BrotherB都在同一个页面中引入

<template>
    <div>
     	<brother-a />
        <hr/>
     	<brother-b />
    </div>
</template>
<script>
    import BrotherA from './BrotherA'
    import BrotherB from './BrotherB'
    export default{
        name:'index',
        components:{BrotherA,BrotherB},
    }
</script>

这样就可以实现在BrotherB组件中触发按钮事件,BrotherA组件就会即时响应事件。

全局使用eventBus,通过vue中提供的provide / inject

provide / inject这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。

在App.vue中使用

export default {
    ...
  	provide() {
	    // eventBus挂载的事件: add
	    return {
	        eventBus: this.eventBus,
	    }
  	}
    ...
}

在兄弟组件BrotherA中使用

export default {
    inject: ['eventBus'],

	methods: {
		add(...arg) {
		  	this.num++
		    ​console.log(...arg)
		},
	},
	created() {
		this.eventBus.$on('add', this.add)
	},
	beforeDestroy() {
		this.eventBus.$off('add', this.add)
	}
}

在兄弟组件BrotherB中使用

export default {
	inject: ['eventBus'],
​	methods: {​
		add() {​ 
			this.eventBus.$emit('add')​ 
		}
	}
}
%