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