Vue實(shí)現(xiàn)組件間通信的幾種方式(多種場景)
以下是我在開發(fā)中用到過的vue組件之間的通信方式,不同的場景使用不同的方式,基本滿足所有開發(fā)場景中的通信需求,從最簡單的事例著手,講述如何使用,話不多說直接開始,滿滿的干貨,建議看完。
1、Props
父 >>> 子 (Props)
一個(gè)組件里面引入另外一個(gè)組件,此時(shí)構(gòu)成了一種“父子關(guān)系”,當(dāng)前組件為“父”,引入的組件為“子”,如當(dāng)前組件(父),在父組件中通過 “:message” 向子組件通信。
<template> <div class="parent-box"> <div> <div>我是父頁面</div> <div>{{message}}</div> </div> <children :message="toChildrenMsg"></children> </div> </template> <script> import Children from './Children.vue' //當(dāng)前頁引入子組件 export default { name:"Parent", components:{ Children }, data(){ return { message:'我是父頁面的內(nèi)容', toChildrenMsg:'從父頁面?zhèn)鬟^到子頁面的內(nèi)容' } } } </script>
在子組件通過props進(jìn)行接收,注意子組件props里面接收的對象名稱必須與父組件中在子組件綁定的名稱一致,當(dāng)前例子為“message”,可以在組件return中this.的方式使用props里面的值。
<template> <div class="children-box"> <div> <div>我是子頁面</div> <div>{{message}}</div> </div> </div> </template> <script> export default { name:"Children", props:{ message:{ type:String, //類型判斷 default:'' //默認(rèn)值 } } } </script>
子組件接收到父組件傳過來的內(nèi)容,實(shí)現(xiàn)效果如下圖所示:
子 >>> 父 ($emit)
在子組件中通過this.$emit()方法向父組件通信,如下,點(diǎn)擊觸發(fā)事件,執(zhí)行this.$emit('fromChildMethod'),觸發(fā)父組件的fromChildMethod方法。
<template> <div class="children-box"> <div> <div>我是子頁面</div> <div>{{message}}</div> <div><span @click="toParentMethod">點(diǎn)擊觸發(fā)父頁面事件</span></div> </div> </div> </template> <script> export default { name:"Children", props:{ message:{ type:String, default:'' } }, methods:{ toParentMethod(){ this.$emit('fromChildMethod') } } } </script>
在父組件的子組件上綁定fromChildMethod方法,對該方法進(jìn)行監(jiān)聽,當(dāng)該方法觸發(fā)時(shí),執(zhí)行父組件中相應(yīng)的方法fromChild。
<template> <div class="parent-box"> <div> <div>我是父頁面</div> <div style="font-size:12px;">{{message}}</div> <div style="font-size:12px;color:red">{{fromChildMsg}}</div> </div> <children :message="toChildrenMsg" @fromChildMethod="fromChild"></children> </div> </template> <script> import Children from './Children.vue' export default { name:"Parent", components:{ Children }, data(){ return { message:'我是父頁面的內(nèi)容', toChildrenMsg:'從父頁面?zhèn)鬟^到子頁面的內(nèi)容', fromChildMsg:'' } }, methods:{ fromChild(){ this.fromChildMsg = '子頁面觸發(fā)的方法' //監(jiān)聽到子組件觸發(fā)的方法,顯示該內(nèi)容 } } } </script>
當(dāng)點(diǎn)擊子組件的對應(yīng)的span,觸發(fā)方法,向父組件進(jìn)行通知。
小結(jié):父傳子,props;子傳父,this.$emit();觸發(fā)、監(jiān)聽名稱須一致。
2、Bus事件總線
真實(shí)的場景中,組件不僅僅是“父子”關(guān)系,還有“兄弟”關(guān)系跟跨層級組件等等。這時(shí)候props跟$emit可能就不太適用了,這時(shí)候它出現(xiàn)了,那就是Bus(事件總線),父子組件同樣適用。
Bus之觸發(fā)$emit、監(jiān)聽$on、關(guān)閉$off,主要用到的就是$emit跟$on。
先在項(xiàng)目中新建一個(gè)文件夾bus,里面有個(gè)index.js文件,創(chuàng)建一個(gè)新的Vue實(shí)例,然后導(dǎo)出模塊。
接下來import這個(gè)新的Vue實(shí)例,也就是bus,常用的兩種導(dǎo)入方式,一種是全局導(dǎo)入,另外一種是局部導(dǎo)入(需每個(gè)組件都導(dǎo)入一次)。以下為全局導(dǎo)入,在main.js里面將該bus作為當(dāng)前Vue實(shí)例的原型方法,能直接在各組件里面通過this.bus的方式調(diào)用。
import Vue from 'vue' import App from './App' import bus from './bus/index' Vue.prototype.bus = bus new Vue({ el: '#app', components: { App }, template: '<App/>' })
下面展示實(shí)現(xiàn)bus通信過程,場景為父子,同樣的,兄弟、跨層級用法與其類似:
Parent組件中向Children組件通信,通過this.bus.$emit()觸發(fā)
<template> <div class="parent-box"> <div> <div>我是父頁面</div> <div @click="toChildBus"><span>向子組件通信</span></div> </div> <children></children> </div> </template> <script> import Children from './Children.vue' export default { name:"Parent", components:{ Children }, methods:{ toChildBus(){ let val = '父組件向子組件通信' this.bus.$emit('toChild',val) //val為傳過去的值,非必傳 } } } </script>
Children組件監(jiān)聽Parent組件觸發(fā)的事件(在mounted階段進(jìn)行綁定監(jiān)聽),注意事件名稱要一致,通過this.bus.$on()監(jiān)聽,當(dāng)總線中監(jiān)聽到觸發(fā)該方法,拿到傳過來的值(也可以在里面執(zhí)行自定義方法)。
<template> <div class="children-box"> <div> <div>我是子頁面</div> <div style="font-size:12px;color:blue;">{{fromParentMsg}}</div> </div> </div> </template> <script> export default { name:"Children", data(){ return { fromParentMsg:'' } }, mounted(){ this.bus.$off('toChild') this.bus.$on('toChild',val=>{ this.fromParentMsg = val //此處為復(fù)制操作,也可在里面執(zhí)行相應(yīng)的方法 }) } } </script>
效果圖:
總結(jié):父子,兄弟,跨級(祖孫等)通信寫法相同,就不一一舉例了,都是通過this.bus.$emit()觸發(fā),通過this.bus.$on()監(jiān)聽,執(zhí)行相應(yīng)的操作,切記:觸發(fā)、監(jiān)聽名稱必須相同!
3、Vuex狀態(tài)管理庫
Vuex相當(dāng)于一個(gè)倉庫,你可以往倉庫里面放一些東西,保持存進(jìn)去的時(shí)的狀態(tài),可以修改,也可以在需要的時(shí)候取出,是一個(gè)全局狀態(tài)。本次只講如何使用vuex進(jìn)行通信,不深究其原理。
安裝vuex
npm install vuex --save
這里我新建一個(gè)文件夾,名稱為store,里面有一個(gè)index.js文件,創(chuàng)建一個(gè)Vuex.Store實(shí)例,然后導(dǎo)出這個(gè)實(shí)例,從圖中可以明確看出store的大致結(jié)構(gòu)及其要素,具體不展開講,關(guān)于vuex的相關(guān)文章數(shù)不勝數(shù),可以自行去了解,這里主要講大致用法。
在mian.js全局引入,之后就可以直接使用了。
import Vue from 'vue' import App from './App' import router from './router' import bus from './bus/index' import store from './store/index' Vue.config.productionTip = false Vue.prototype.bus = bus new Vue({ el: '#app', router, store, components: { App }, template: '<App/>' })
方式一,this.$store.state.xxx,直接對state進(jìn)行操作,在一個(gè)組件mounted階段將值存如store中,當(dāng)然也可在你想在的方法中進(jìn)行操作。
<template> <div class="parent-box"> <div> <div>我是父頁面</div> </div> <children></children> </div> </template> <script> import Children from './Children.vue' export default { name:"Parent", components:{ Children }, data(){ return { fromChildMsg:'' } } mounted(){ this.$store.state.msg = '父組件存入' //在此處通過方式一存起來 } } </script>
其他組件從store中取出,當(dāng)然同樣也可以進(jìn)行修改。
<template> <div class="children-box"> <div> <div>我是子頁面</div> <div @click="fromStore"><span>從store里面取</span></div> <div>{{fromStoreMsg}}</div> </div> </div> </template> <script> export default { name:"Children", data(){ return { fromStoreMsg:'' } }, methods:{ fromStore(){ this.fromStoreMsg = this.$store.state.msg } } } </script>
效果圖:
方式二,通過this.$store.getters.xxx、mapGetters進(jìn)行取出。
// store/index.js getters:{ getMsg:state=>{ return state.msg } }, //組件中取 this.$store.getters.getMsg //也可以用mapGetters的方式 import { mapGetters } from 'vuex' computed: { ...mapGetters(['getMsg']) },
對store存入數(shù)據(jù)該可以用mutations、actions(可異步)進(jìn)行存入,具體就不展開了,有興趣可以自己去深究。
4、Router
可以通過動(dòng)態(tài)路由、路由跳轉(zhuǎn)方式進(jìn)行傳值,如this.$router.push({path:'xxx',query:{value:'xxx'}}),在跳轉(zhuǎn)的時(shí)候順便傳值,通過this.$route.params.value和this.$route.query.value獲取到傳過來的參數(shù)。該方式有局限性,只能在相互跳轉(zhuǎn)的組件通信取值,且直接在跳轉(zhuǎn)之后的頁面進(jìn)行刷新取不到值,視情況而用。
5、緩存
sessionStorage、localStorage、cookie
多個(gè)組件之間的通信除了可以用bus、store之外,還比較一種常用的方式--緩存,在同一個(gè)窗口不關(guān)閉的情況下,該窗口下的其他組件都可以取到緩存中已經(jīng)存好的值,利用sessionStorage.setItem(key,value)、localStorage.setItem(key,value)等將值存起來,其他組件可以通過sessionStorage.getItem(key)、localStorage.getItem(key)等方式拿到,多個(gè)頁面共享緩存數(shù)據(jù),刷新頁面數(shù)據(jù)不會(huì)銷毀,可以用sessionStorage.removeItem(key)、localStorage.removeItem(key)的方式將緩存移除,可用場景還是比較多的。
總結(jié):大致介紹vue組件中幾種常用的通信、傳值方式,考慮不同的場景使用不同的方式,提高開發(fā)效率,減少bug的產(chǎn)生。
到此這篇關(guān)于Vue實(shí)現(xiàn)組件間通信的幾種方式(多種場景)的文章就介紹到這了,更多相關(guān)Vue 組件通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue項(xiàng)目本地開發(fā)完成后部署到服務(wù)器后報(bào)404錯(cuò)誤解決方案
很多時(shí)候我們發(fā)現(xiàn)辛辛苦苦寫的VueJs應(yīng)用經(jīng)過打包后在自己本地搭建的服務(wù)器上測試沒有什么問題,但真正放在服務(wù)器上后會(huì)發(fā)現(xiàn)或多或少的問題,這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目本地開發(fā)完成后部署到服務(wù)器后報(bào)404錯(cuò)誤的解決方案,需要的朋友可以參考下2024-01-01Vue引入sign-canvas實(shí)現(xiàn)簽名畫板效果
這篇文章主要介紹了Vue引入sign-canvas實(shí)現(xiàn)簽名畫板,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03vue 根據(jù)數(shù)組中某一項(xiàng)的值進(jìn)行排序的方法
這篇文章主要介紹了vue 根據(jù)數(shù)組中某一項(xiàng)的值進(jìn)行排序的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08vue實(shí)現(xiàn)右側(cè)滑出層動(dòng)畫
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)右側(cè)滑出層動(dòng)畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04vue中將el-switch值true、false改為number類型的1和0
這篇文章主要介紹了vue中將el-switch值true、false改為number類型的1和0問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10vue3+ts+vite使用el-table表格渲染記錄重復(fù)情況
這篇文章主要給大家介紹了關(guān)于vue3+ts+vite使用el-table表格渲染記錄重復(fù)情況的相關(guān)資料,我們可以通過合并渲染、數(shù)據(jù)緩存或虛擬化等技術(shù)來減少重復(fù)渲染的次數(shù),文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12vue使用ECharts實(shí)現(xiàn)折線圖和餅圖
這篇文章主要為大家詳細(xì)介紹了vue使用ECharts實(shí)現(xiàn)折線圖和餅圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09vuex項(xiàng)目中登錄狀態(tài)管理的實(shí)踐過程
由于狀態(tài)零散地分布在許多組件和組件之間的交互中,大型應(yīng)用復(fù)雜度也經(jīng)常逐漸增長,為了解決這個(gè)問題,Vue 提供 vuex,這篇文章主要給大家介紹了關(guān)于vuex項(xiàng)目中登錄狀態(tài)管理的相關(guān)資料,需要的朋友可以參考下2021-09-09