eventBus
在vue3 中 off和$once 实例方法已被移除,因此我们无法像在vue2中使用 这些方法实现eventBus,不过,可以使用一个插件来提供类似的功能,mitt插件。
插件地址:www.npmjs.com/package/mit…
安装插件
pnpm install mitt -S
mitt插件提供了四个方法:
all() : 返回当前所有事件监听器的集合。
emit() : 触发一个自定义事件,并且可以携带参数
on() : 监听当前实例上的自定义事件
off() : 移除对自定义事件的监听
下面展示如何使用
配置插件
//main.ts
//使用mitt插件
import mitt from 'mitt'
//挂载全局属性
app.config.globalProperties.$eventBus = mitt()
兄弟组件之间传参
现在有组件A和组件B,在index.vue中引入两个组件同级,A和B属于兄弟组件,下面实现兄弟组件之间的传参
组件A
//A.vue
<template>
<div class="A-container">
<p class="name">A组件</p>
<n-button @click="handleClick()">点击</n-button>
<!--<AS></AS>-->
</div>
</template>
<script lang="ts" setup>
import AS from '@/components/eventBus/AS.vue'
import { getCurrentInstance } from 'vue'
const vm = getCurrentInstance()
const handleClick = () => {
vm?.proxy.$eventBus.emit('on-click', 1)
}
</script>
<style scoped lang="scss">
.A-container {
height: 400px;
width: 500px;
background: #cacaca;
.name {
font-weight: 600;
font-size: 24px;
}
}
</style>
组件B
//B.vue
<template>
<div class="B-container">
<p class="name">B组件</p>
<div class="data">{{ count }}</div>
</div>
</template>
<script lang="ts" setup>
import { getCurrentInstance, onUnmounted, ref } from 'vue'
const vm = getCurrentInstance()
let count = ref<number>(0)
//监听自定义事件
vm?.proxy?.$eventBus.on('on-click', (num) => {
count.value += num
})
onUnmounted(() => {
//在组建取消挂载的时候,移除对自定义事件的监听
vm?.proxy?.$eventBus.off('on-click')
})
</script>
<style scoped lang="scss">
.B-container {
height: 400px;
width: 500px;
background: #54a29e;
.name,
.data {
font-weight: 600;
font-size: 24px;
}
}
</style>
父组件
//index.vue
<template>
<div class="eventBus-container">
<p class="name">父组件</p>
<p class="data">{{ data }}</p>
<A></A>
<B></B>
</div>
</template>
<script setup lang="ts">
import { getCurrentInstance, onUnmounted, ref } from 'vue'
import A from '@/components/eventBus/A.vue'
import B from '@/components/eventBus/B.vue'
const vm = getCurrentInstance()
let data = ref(0)
//监听自定义事件
vm?.proxy?.$eventBus.on('handleIndex', (num) => {
data.value += num
})
onUnmounted(() => {
//移除对自定义事件的监听
vm?.proxy?.$eventBus.off('handleIndex')
})
</script>
<style lang="scss" scoped>
.eventBus-container {
text-align: center;
background: aquamarine;
padding-left: 100px;
.name,
.data {
font-weight: 600;
font-size: 24px;
}
}
</style>
效果
跨组件传参
子孙组件AS
//AS 组件
<template>
<div class="AS-container">
<p class="name">子孙组件</p>
<n-button @click="handleClick()">点击</n-button>
</div>
</template>
<script lang="ts" setup>
import { getCurrentInstance } from 'vue'
const vm = getCurrentInstance()
const handleClick = () => {
vm?.proxy.$eventBus.emit('handleIndex', 1)
}
</script>
<style lang="scss" scoped>
.AS-container {
height: 200px;
width: 300px;
background: palegreen;
.name {
font-size: 18px;
font-weight: 600;
}
}
</style>
组件 A
在A组件中引入AS.vue,A.vue 和 AS.vue为父子组件。
//A.vue
<template>
<div class="A-container">
<p class="name">A组件</p>
<n-button @click="handleClick()">点击</n-button>
<AS></AS>
</div>
</template>
<script lang="ts" setup>
import AS from '@/components/eventBus/AS.vue'
import { getCurrentInstance } from 'vue'
const vm = getCurrentInstance()
const handleClick = () => {
vm?.proxy.$eventBus.emit('on-click', 1)
}
</script>
<style scoped lang="scss">
.A-container {
height: 400px;
width: 500px;
background: #cacaca;
.name {
font-weight: 600;
font-size: 24px;
}
}
</style>
父组件
父组件为index index中引入了A组件 ,index.vue 和 A.vue为父子组件; A.vue中引入了AS.vue ,
A.vue和AS.vue为父子组件, AS.vue 为index.vue的子孙组件,AS.vue传参到index.vue属于是跨组件传参
//index.vue
<template>
<div class="eventBus-container">
<p class="name">父组件</p>
<p class="data">{{ data }}</p>
<A></A>
<B></B>
</div>
</template>
<script setup lang="ts">
import { getCurrentInstance, onUnmounted, ref } from 'vue'
const vm = getCurrentInstance()
let data = ref(0)
//监听自定义事件
vm?.proxy?.$eventBus.on('handleIndex', (num) => {
data.value += num
})
onUnmounted(() => {
//移除对自定义事件的监听
vm?.proxy?.$eventBus.off('handleIndex')
})
import A from '@/components/eventBus/A.vue'
import B from '@/components/eventBus/B.vue'
</script>
<style lang="scss" scoped>
.eventBus-container {
text-align: center;
background: aquamarine;
padding-left: 100px;
.name,
.data {
font-weight: 600;
font-size: 24px;
}
}
</style>
效果
点击子孙组件中的按钮,可以发现父组件中的数字发生了变化,说明跨组件传参成功
这是一个子孙组件向父组件传递参数的例子,父组件向子孙组件也是一样的流程,需要在父组件中使用on 监听事件既可。