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)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
使用yarn?build?打包vue項目時靜態(tài)文件或圖片未打包成功的問題及解決方法
這篇文章主要介紹了使用yarn?build?打包vue項目時靜態(tài)文件或圖片未打包成功的問題及解決方法,解決方法不復雜通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2023-08-08vue父組件向子組件(props)傳遞數(shù)據(jù)的方法
這篇文章主要介紹了vue父組件向子組件(props)傳遞數(shù)據(jù)的方法,文中給大家補充介紹了vue父子組件間傳值(props)的實現(xiàn)代碼,需要的朋友可以參考下2018-01-01Vue手把手教你擼一個 beforeEnter 鉤子函數(shù)
這篇文章主要介紹了Vue手把手教你擼一個 beforeEnter 鉤子函數(shù),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04vue3使用defineModel實現(xiàn)父子組件雙向綁定
這篇文章主要個給大家介紹了在vue3中使用defineModel進行父子組件中的雙向綁定,文中通過代碼示例給大家介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下2024-01-01前端實現(xiàn)簡單的sse封裝方式(React hook Vue3)
這篇文章主要介紹了前端實現(xiàn)簡單的sse封裝方式(React hook Vue3),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08Vue?element-ui中表格過長內容隱藏顯示的實現(xiàn)方式
在Vue項目中,使用ElementUI渲染表格數(shù)據(jù)時,如果某一個列數(shù)值長度超過列寬,會默認換行,造成顯示不友好,下面這篇文章主要給大家介紹了關于Vue?element-ui中表格過長內容隱藏顯示的實現(xiàn)方式,需要的朋友可以參考下2022-09-09