Vue 之全域性事件匯流排和訊息訂閱與釋出
之前我們實現了子元件向父元件傳遞資料,很明顯,這是不夠的,看完這篇部落格,無論哪兩個元件之間傳遞和接收資料都沒有問題!
全域性事件匯流排(適用於任意元件間通訊) 原理:(看圖理解)
主要就是通過往 x 身上放事件,然後事件的回撥要放在想要獲取資料的元件身上,誰要傳資料就呼叫 x 身上對應的事件並往裡面存資料就可以了,相當於一箇中間商(哎,不得不說,它一出生就被利用了)
當然不是誰都能但此大任的,x 需要具備兩個條件:
-
所有元件都可以看到
-
x 身上有 on、on 、on、off 、$emit 方法
統一給 x 命名為 $bus
我們將其定義在 main.js 檔案中,建立在 vm 的例項物件身上,因為 vm 例項物件只有一個
建立全域性事件匯流排有兩種方法:
1、
const Demo = Vue.extend({})
const d = new Demo()
Vue.prototype.$bus = d
(定義在建立 Vue 的外面)
2、
new Vue({
......
beforeCreate(){
Vue.prototype.$bus = this //安裝全域性事件匯流排, $bus 就是當前應用的 vm
},
})
複製程式碼
new Vue({
render: h => h(App),
beforeCreate(){
Vue.prototype.$bus = this //安裝全域性事件匯流排
}
}).$mount('#app')
複製程式碼
使用事件匯流排:
- 接收資料:A 元件想接收資料,則在 A 元件中給 $bus 繫結自定義事件,事件的回撥留在 A 元件自身
mounted() { //或者後面指向的是一個方法,方法在 methods 裡面定義 //在全域性事件匯流排 bus中繫結一個hello事件,後面的回撥是箭頭函式,用於接收資料this.bus 中繫結一個 hello 事件,後面的回撥是箭頭函式,用於接收資料 this.bus中綁定一個hello事件,後面的回調是箭頭函數,用於接收數據this.bus.$on("hello", (value) => { console.log("我獲取到了資料", value); }); },
- 提供資料:
methods: { sentMyName(){ //在該方法中觸發 hello 這個事件,把資料傳過去 this.bus.bus.bus.emit('hello',this.myName) } }, 用這個方法的好處就是!我們就不需要再在標籤裡繫結自定義事件了,直接把事件在 $bus 裡建立,再在要傳資料的地方呼叫它就可以了!
當然還有個注意點,如果某個事件或繫結事件的元件你不用了,那要養成隨時解綁的好習慣!不要佔著空間不用,會導致空間浪費從而出現卡頓
最好在 beforeDestroy 鉤子中,用 $off 去解綁當前元件所用到的事件
在繫結事件的元件中解綁(即需要資料的元件)
beforeDestroy() { //解綁 bus中名為hello的事件this.bus 中 名為 hello 的事件 this.bus中名為hello的事件this.bus.off("hello"); }, 切記!this.bus.off()裡面一定要寫要解綁的事件,不然off() 裡面一定要寫要解綁的事件,不然 off()裡面一定要寫要解綁的事件,不然bus 中所有的事件都會被解綁!後果很嚴重!!!!
訊息訂閱與釋出(適用於任意元件間通訊) 原理:
簡單理解:
需要資料的元件:訂閱訊息 提供資料的元件:釋出訊息
這個相比第一種方法就要麻煩那麼一丟丟了,它需要安裝 pubsub,我們開啟 VScode 的控制檯,輸入 npm i pubsub-js,進行安裝
在傳資料和接收資料的元件中都要通過 import pubsub from 'pubsub-js' 引入這個檔案
然後就可以開始使用了
接收資料:A 元件想接收資料,則在 A 元件中訂閱訊息,訂閱的回撥留在 A 元件自身
this.pubId = pubsub.subscribe('hello',(msgName,data)=>{
console.log('我接收到資料了',data);
})
複製程式碼
這裡有一個注意點,那就是回撥函式的第一個引數 msgName,代表的是 hello,即訂閱的訊息名,這個必須要寫,因為預設第一個引數就是訊息名,第二個引數才是資料,前端培訓所以不管如何,第一個要佔個位,你可以給它取個名字,或者用下劃線 _ 佔位
提供資料:
methods: { sentMyName(){ pubsub.publish('hello',this.myName) } }, 當然如果訂閱的訊息不用了,也要將其刪除,不能佔用空間,但是刪除訂閱訊息不是用 $off ,而是 publish.unsubscribe(this.pubId),其中 this.pubId 是每個訊息建立的時候都會有一個 id,就像定時器一樣,我們刪除就刪除它對應的 id 號就可以了
beforeDestroy() { pubsub.unsubscribe(this.pubId) }, 對比兩者我們用的更多的是前者,因為它是 Vm 裡面建立的,不需要再匯入包
最後再分享一個方法: