概况
vue3中常见的组件通信
组件关系 | 传递方式 |
---|---|
父传子 | 1. props 2. v-model 3. $refs 4. 默认插槽、具名插槽 |
子传父 | 1. props 2. 自定义事件 3. v-model 4. $parent 5. 作用域插槽 |
祖传孙、孙传祖 | 1. $attrs 2. provide、inject |
兄弟间、任意组件间 | 1. mitt 2. pinia |
Vue2.x 使用 EventBus 事件总线进行兄弟组件通信,而在Vue3中事件总线模式已经被移除,官方建议使用外部的、实现了事件触发器接口的库,例如 mitt 或 tiny-emitter。今天来说说mitt。
安装
npm install --save mitt
yarn add mitt
pnpm install mitt
基本用法
mitt().on() 绑定事件
用来绑定事件,接收两个参数,第一个参数是事件名,第二个参数是事件触发时的回调函数;
mitt().emit() 触发事件
用来触发事件,参数为事件名;
mitt().off()卸载某个事件
用来解绑事件,参数为事件名;
mitt().all.clear()卸载全部事件
all有clear属性,直接调用clear()属性可以解绑全部事件。
//绑定事件test1,当事件触发时执行回调
emitter.on('test1',()=>{
console.log('test1被调用了')
})
//绑定事件test2,当事件触发时执行回调
emitter.on('test2',()=>{
console.log('test2被调用了')
})
//绑定事件test3,当事件触发时执行回调
emitter.on('test3',()=>{
console.log('test3被调用了')
})
//触发事件,每间隔1秒触发一次
setInterval(()=>{
//触发事件test1
emitter.emit('test1')
//触发事件test2
emitter.emit('test2')
//触发事件test3
emitter.emit('test3')
},1000)
//解绑事件,2秒后解绑test1
setTimeout(()=>{
emitter.off('test1')
console.log('--------test1解绑了')
},2000)
//解绑事件,4秒后解绑所有事件
setTimeout(()=>{
emitter.all.clear()
console.log('--------所有的事件解绑了')
},4000)
使用方式
使用方式一:全局使用
在 main.ts 中注册挂载到全局
import { createApp } from 'vue'
import App from './App.vue'
//引入
import mitt from 'mitt'
const app = createApp(App)
// vue3挂载到全局
app.config.globalProperties.$mitt = mitt();
app.mount('#app')
在home.vue组件中使用 emit 发送信息
<template>
<div class="home-container">
<p>这里是home组件</p>
<button @click="sendMitt">$mitt发送数据</button>
<About></About>
</div>
</template>
<script lang="ts" setup>
import { getCurrentInstance, ref, ComponentInternalInstance } from 'vue';
import About from '../about/about.vue'
const { appContext } = getCurrentInstance() as ComponentInternalInstance;
const money = ref<number>(98);
const sendMitt = () => {
appContext.config.globalProperties.$mitt.emit('moneyEvent', money.value += 2);
}
</script>
在about.vue组件中使用 on 接收信息
使用方式二:组件中引用
新建bus.ts 文件
import mitt from "mitt";
const emiter = mitt();
export default emiter;
在home.vue组件中引入并使用 emit 发送信息
<template>
<div class="home-container">
<p>这里是home组件</p>
<button @click="sendMitt">$mitt发送数据</button>
<About></About>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import About from '../about/about.vue'
import emitter from '../../utils/bus'
const money = ref<number>(98);
const sendMitt = () => {
emitter.emit('moneyEvent', money.value += 2);
}
</script>
在about.vue组件中引入并使用 on 接收信息
<template>
<div class="about-container">
<p>这里是about组件</p>
<p>接收到的数据:{{ amount }}</p>
</div>
</template>
<script lang="ts" setup>
import { ref, onBeforeMount, onMounted } from 'vue';
import emitter from '../../utils/bus'
const amount = ref(0);
onMounted(() => {
emitter.on('moneyEvent', (res: any) => {
amount.value = res;
});
})
onBeforeMount(() => {
emitter.off('moneyEvent');
});
</script>