Vue中如何使用event bus进行组件通讯?

1. 什么是event bus

Event bus是一种Vue实例,它可以在不同组件之间传递消息。Vue.js应用程序是一个由组件构成的层次结构,这些组件可以相互通信并且组成一个功能完整的整体。在Vue的组件之间进行通信的中间件是事件总线(也称为事件bus)。事件bus是将我们的应用程序所有组件连接在一起的便捷方式。它是一种Vue实例,通常位于main.js文件中,是全局性的,因此可以让不同组件中的消息彼此通信。

// 导入Vue模块

import Vue from 'vue'

// 创建bus

export const bus = new Vue()

2. 什么时候需要使用event bus

2.1 父子组件之间通信

当一个父组件和一个或多个子组件之间需要进行相互通信时,可以使用event bus来进行通信。使用event bus来进行通信的好处是,父组件不需要知道它的子组件接收到了消息,子组件也不需要知道消息是从父组件传递过来的。这样可以实现父子组件之间解耦。

2.2 兄弟组件之间通信

当两个或多个兄弟组件之间需要进行消息传递时,可以使用event bus来进行通信。这种情况下,消息的发送者和接收者可能位于不同的组件中。

2.3 跨级组件之间通信

当两个或多个位于不同层级的组件需要进行消息传递时,也可以使用event bus来进行通信。可以将事件总线放在共同的祖先级组件中,并由祖先级组件分配接收器。

3. event bus的使用方法

在Vue.js应用程序中使用event bus非常简单。要使用Vue的事件总线,您需要使用Vue实例来实例化它,并在全局范围内引用它。这可以通过在main.js文件中进行创建,使用Vue实例作为事件管理器。然后,在需要传递消息的组件中,使用$emit方法来发送消息,使用$on方法来接收消息。$emit方法触发指定的事件,$on方法监听指定的事件。

3.1 在main.js中创建event bus实例

import Vue from 'vue'

// 创建event bus实例

export const eventBus = new Vue();

3.2 发送消息:$emit

要发送消息,请使用事件总线的$emit方法。该$emit方法接受两个参数:第一个参数是要发送的事件名称,第二个参数是要传递的数据。例如:

eventBus.$emit('my-event', 'Hello World!');

上面的代码将在事件总线上触发一个名为"my-event"的事件,并传递字符串"Hello World!"作为参数。

3.3 接收消息:$on

要接收事件总线发送的消息,请使用$on方法。该方法接受两个参数:第一个参数是要监听的事件名称,第二个参数是具有可选回调函数的函数。该回调函数具有一个参数,该参数是传递给事件的数据。例如:

eventBus.$on('my-event', (data) => {

console.log(data); // 输出 "Hello World!"

});

上述代码确保在事件总线上监听名为"my-event"的事件。当该事件被触发时,回调函数将被调用,传递给它的参数是传递给事件总线的数据。

4. event bus应用实例

4.1 父组件向子组件传值

我们有一个父组件和一个子组件,并且我们希望将数据传递给子组件。在这种情况下,我们可以使用事件总线来传递数据。首先,我们需要在父组件中触发事件,子组件中监听该事件来获取数据。在父组件中,我们需要使用$emit方法来触发事件,并将传递给事件总线的数据作为参数传递给它。在子组件中,我们使用$on方法监听该事件,并在回调函数中获取数据。下面是该场景的代码实例:

// 父组件

<template>

<div>

<button @click="sendMessage">发送消息到子组件</button>

<Child></Child>

</div>

</template>

<script>

import { eventBus } from '@/main.js'

export default {

name: 'Parent',

data() {

return {

message: 'Hello from parent component'

}

},

methods: {

sendMessage() {

eventBus.$emit('message-from-parent', this.message)

}

}

}

</script>

// 子组件

<template>

<div>

子组件收到的消息是:{{ messageFromParent }}

</div>

</template>

<script>

import { eventBus } from '@/main.js'

export default {

name: 'Child',

data() {

return {

messageFromParent: ''

}

},

created() {

eventBus.$on('message-from-parent', (data) => {

this.messageFromParent = data

})

}

}

</script>

在上述示例中,父组件包含一个按钮和一个子组件。当按钮被点击时,它会调用sendMessage方法,并使用事件总线触发名为"message-from-parent"的事件,并将父组件中的消息作为参数传递给它。在子组件中,我们在created生命周期函数中使用$on方法来监听该事件并获取传递的消息。

4.2 子组件向父组件传值

在这种情况下,我们有一个子组件和一个父组件,并且我们希望将子组件中的数据传递给父组件。我们可以使用事件总线来实现它。在子组件中,我们需要使用$emit方法来触发事件,并将要传递的数据作为参数传递给它。在父组件中,我们使用$on方法监听该事件,并在回调函数中获取数据。下面是该场景的代码实例:

// 子组件

<template>

<div>

<button @click="sendMessage">发送消息到父组件</button>

</div>

</template>

<script>

import { eventBus } from '@/main.js'

export default {

name: 'Child',

data() {

return {

message: 'Hello from child component'

}

},

methods: {

sendMessage() {

eventBus.$emit('message-from-child', this.message)

}

}

}

</script>

// 父组件

<template>

<div>

<Child @message-from-child="receiveMessage"></Child>

父组件收到的消息是:{{ messageFromChild }}

</div>

</template>

<script>

import Child from '@/components/Child.vue'

import { eventBus } from '@/main.js'

export default {

name: 'Parent',

components: {

Child

},

data() {

return {

messageFromChild: ''

}

},

methods: {

receiveMessage(message) {

this.messageFromChild = message

}

},

created() {

eventBus.$on('message-from-child', (data) => {

this.receiveMessage(data)

})

}

}

</script>

在上述示例中,子组件包含一个按钮,当按钮被点击时,它将使用事件总线触发名为"message-from-child"的事件,并将子组件中的消息传递给它。在父组件中,我们在Child组件的props中声明一个@message-from-child,并将它绑定到receiveMessage方法。当子组件触发该事件时,receiveMessage方法将被调用,并将接收的数据存储到父组件中。同时,我们在父组件的created生命周期函数中使用$on方法监听该事件,并在回调函数中调用receiveMessage方法。

4.3 兄弟组件之间传值

在这种情况下,我们有两个兄弟组件并且他们需要相互通信传递数据。我们可以使用事件总线来实现它。和前面两种情况一样,组件需要分别使用$on方法和$emit方法,以用于监听和触发事件。下面是该场景的代码实例:

// 组件A

<template>

<div>

<button @click="sendMessage">发送消息</button>

</div>

</template>

<script>

import { eventBus } from '@/main.js'

export default {

name: 'ComponentA',

data() {

return {

message: 'Hello from Component A'

}

},

methods: {

sendMessage() {

eventBus.$emit('message-between-components', this.message)

}

}

}

</script>

// 组件B

<template>

<div>

组件B收到的消息是:{{ messageFromComponentA }}

</div>

</template>

<script>

import { eventBus } from '@/main.js'

export default {

name: 'ComponentB',

data() {

return {

messageFromComponentA: ''

}

},

created() {

eventBus.$on('message-between-components', (data) => {

this.messageFromComponentA = data

})

}

}

</script>

在本例中,组件A包含一个按钮,该按钮在点击时会使用事件总线触发名为"message-between-components"的事件,并将数据作为参数传递给它。组件B监听该事件,当该事件被触发时,它将执行一个回调函数以接收传递的数据。

5. event bus的缺点

尽管事件总线是一种方便的方法,可以在组件之间实现通信,并让组件相互解耦,但是它也存在一些缺点:

5.1 事件总线缺乏命名空间

在大型应用程序中,事件总线可能会被多个开发人员使用,这可能会导致冲突或难以维护的代码。

5.2 易于出现bug

任何组件都可以触发和监听事件总线中的任何事件。因此,在应用程序变得越来越大时,调试问题可能会变得困难。

5.3 难以调试

除了比组件之间的传递更加不透明外,事件总线还具有更难以调试的缺点。不像组件之间的通信,事件总线中的消息可能需要在多个层次结构上进行传递,并且可以通过多个通道进行传递。

6. 总结

在Vue.js应用程序中,通过使用事件总线可以方便地在组件之间进行通信。事件总线是Vue的实例,它可以在不同组件之间传递消息。使用事件总线有许多好处,包括帮助组件解耦、方便跨层次结构进行通信等。但是,事件总线也存在一些缺点,包括较不规范的使用容易出错等。在使用事件总线时,必须小心使用,以确保在代码增长时维护其可读性和可维护性。