Vue3中的常見組件通信之mitt使用詳解
Vue3中的常見組件通信之mitt
概述
? 在vue3中常見的組件通信有props、mitt、v-model、 refs、parent、provide、inject、pinia、slot等。不同的組件關系用不同的傳遞方式。
常見的撘配形式如下表所示。
| 組件關系 | 傳遞方式 |
|---|---|
| 父傳子 | 1. props 2. v-model 3. $refs 4. 默認插槽、具名插槽 |
| 子傳父 | 1. props 2. 自定義事件 3. v-model 4. $parent 5. 作用域插槽 |
| 祖?zhèn)鲗O、孫傳祖 | 1. $attrs 2. provide、inject |
| 兄弟間、任意組件間 | 1. mitt 2. pinia |
? props和自定義事件詳見本人另一篇文章:
下面接著上文來繼續(xù)記錄mitt的用法。
mitt
mitt與pubsub訂閱消息與發(fā)布消息功能類似,它可以實現(xiàn)在任意組件間的通信。
安裝mitt及引入mitt
mitt需要安裝,在終端中輸入命令npm i mitt來安裝。
mitt安裝好之后按照工程化的管理需要在src的文件下新建文件夾utils,然后在utils文件夾中新建文件emitter.ts。
在emitter.ts文件中引入mitt,并創(chuàng)建emitter,同時暴露emitter,如下代碼:
//引入mitt import mitt from 'mitt' //調用mitt,得到emitter,emitter可以綁定事件和觸發(fā)事件 const emitter = mitt() //暴露emitter export default emitter
之后需要再在main.ts中引入emitter,如下代碼:
import emitter from '@/utils/emitter'
emitter基本用法
emitter身上有四個方法,分別是
- **on()??*用來綁定事件,接收兩個參數(shù),第一個參數(shù)是事件名,第二個參數(shù)是事件觸發(fā)時的回調函數(shù);
- **emit()??*用來觸發(fā)事件,參數(shù)為事件名;
- **off()??*用來解綁事件,參數(shù)為事件名;
- **all:**all有clear屬性,直接調用clear()屬性可以解綁全部事件。
以下代碼為展示emitter的基本用法:
//綁定事件test1,當事件觸發(fā)時執(zhí)行回調
emitter.on('test1',()=>{
console.log('test1被調用了')
})
//綁定事件test2,當事件觸發(fā)時執(zhí)行回調
emitter.on('test2',()=>{
console.log('test2被調用了')
})
//綁定事件test3,當事件觸發(fā)時執(zhí)行回調
emitter.on('test3',()=>{
console.log('test3被調用了')
})
//觸發(fā)事件,每間隔1秒觸發(fā)一次
setInterval(()=>{
//觸發(fā)事件test1
emitter.emit('test1')
//觸發(fā)事件test2
emitter.emit('test2')
//觸發(fā)事件test3
emitter.emit('test3')
},1000)
//解綁事件,2秒后解綁test1
setTimeout(()=>{
emitter.off('test1')
console.log('--------test1解綁了')
},2000)
//解綁事件,4秒后解綁所有事件
setTimeout(()=>{
emitter.all.clear()
console.log('--------所有的事件解綁了')
},4000)運行后在控制臺輸出如下內容:

emitter在組件中的用法
首先創(chuàng)建一個父組件,兩個子組件,父組件代碼如下:
<template>
<div class="father">
<h3>父組件</h3>
<Child1/>
<Child2/>
</div>
</template>
<script setup lang="ts" name="Father">
import Child1 from './Child1.vue'
import Child2 from './Child2.vue'
</script>
<style scoped>
.father{
margin: 5px;
background-color:rgb(79, 186, 111);
padding: 20px;
color: white;
}
</style>子組件1代碼:
<template>
<div class="child1">
<h3>子組件1</h3>
</div>
</template>
<script setup lang="ts" name="Child1">
</script>
<style scoped>
.child1{
margin: 5px;
background-color: rgba(7, 7, 7, 0.224);
border: 1px solid;
border-color: white;
box-shadow: 0 0 5px;
padding: 10px;
color: #760e0e;
}
</style>子組件2代碼:
<template>
<div class="child2">
<h3>子組件2</h3>
</div>
</template>
<script setup lang="ts" name="Child2">
</script>
<style scoped>
.child2{
margin: 5px;
background-color: rgba(255, 255, 255, 0.224);
border: 1px solid;
border-color: white;
box-shadow: 0 0 5px;
padding: 10px;
color: #05035f;
}
</style>運行效果如下:

然后我們在子組件1中準備一些數(shù)據(jù)如下:
//數(shù)據(jù)
let book = reactive({
name:'西游記',
author:'吳承恩',
price:119.95
})然后在頁面中展示:
<!-- 展示 -->
<h4>圖書名稱:{{ book.name }}</h4>
<h4>圖書作者:{{ book.author }}</h4>
<h4>圖書價格:¥{{ book.price }}</h4>運行效果如下:

接下來在子組件2中引入emitter,然后創(chuàng)建book數(shù)據(jù),給emitter綁定事件,并傳入回調函數(shù):
//引入emitter
import emitter from '@/utils/emitter';
import { reactive } from 'vue';
//數(shù)據(jù)
let book = reactive({
name:'',
author:'',
price:null
})
//給emitter綁定getBook事件,傳入回調函數(shù),回調函數(shù)接收一個參數(shù)
emitter.on('getBook',(value:any)=>{
// console.log(value)
book.name = value.name
book.author = value.author
book.price = value.price
})然后在子組件1中創(chuàng)建一個按鈕,綁定click事件,觸發(fā)getBook事件,并傳遞book參數(shù):
<button @click="emitter.emit('getBook',book)">將book信息發(fā)送給子組件2</button>最后在子組件2中展示接收的到的信息:
<!-- 展示 -->
<h4>圖書名稱:{{ book.name }}</h4>
<h4>圖書作者:{{ book.author }}</h4>
<h4>圖書價格:¥{{ book.price }}</h4>最后運行后頁面效果如下:

點擊按鈕后效果如下:

至此已經(jīng)完成了子組件1向子組件2通信。
子組件1完整代碼如下:
<template>
<div class="child1">
<h3>子組件1</h3>
<!-- 展示 -->
<h4>圖書名稱:{{ book.name }}</h4>
<h4>圖書作者:{{ book.author }}</h4>
<h4>圖書價格:¥{{ book.price }}</h4>
<button @click="emitter.emit('getBook',book)">將book信息發(fā)送給子組件2</button>
</div>
</template>
<script setup lang="ts" name="Child1">
import emitter from '@/utils/emitter';
import { reactive } from 'vue';
//數(shù)據(jù)
let book = reactive({
name:'西游記',
author:'吳承恩',
price:119.95
})
</script>
<style scoped>
.child1{
margin: 5px;
background-color: rgba(7, 7, 7, 0.224);
border: 1px solid;
border-color: white;
box-shadow: 0 0 5px;
padding: 10px;
color: #760e0e;
}
</style>子組件2 的完整代碼如下:
<template>
<div class="child2">
<h3>子組件2</h3>
<!-- 展示 -->
<h4>圖書名稱:{{ book.name }}</h4>
<h4>圖書作者:{{ book.author }}</h4>
<h4>圖書價格:¥{{ book.price }}</h4>
</div>
</template>
<script setup lang="ts" name="Child2">
//引入emitter
import emitter from '@/utils/emitter';
import { reactive } from 'vue';
//數(shù)據(jù)
let book = reactive({
name:'',
author:'',
price:null
})
//給emitter綁定getBook事件,傳入回調函數(shù),回調函數(shù)接收一個參數(shù)
emitter.on('getBook',(value:any)=>{
// console.log(value)
book.name = value.name
book.author = value.author
book.price = value.price
})
</script>
<style scoped>
.child2{
margin: 5px;
background-color: rgba(255, 255, 255, 0.224);
border: 1px solid;
border-color: white;
box-shadow: 0 0 5px;
padding: 10px;
color: #05035f;
}
</style>總結
接收數(shù)據(jù)的組件必須要先綁定事件(訂閱),發(fā)送數(shù)據(jù)的組件要觸發(fā)事件,只要組件中引入了emitter,并執(zhí)行了emitter.emit()代碼并傳遞參數(shù),即可實現(xiàn)任意組件間的通信。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
vue3使用vis繪制甘特圖制作timeline可拖動時間軸及時間軸中文化(推薦)
這篇文章主要介紹了vue3使用vis繪制甘特圖制作timeline可拖動時間軸,時間軸中文化,本文結合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-02-02
一篇看懂vuejs的狀態(tài)管理神器 vuex狀態(tài)管理模式
一篇看懂vuejs的狀態(tài)管理神器,Vuex一個專為Vue.js應用程序開發(fā)的狀態(tài)管理模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04

