1. 程式人生 > 其它 >Vue 之全域性事件匯流排和訊息訂閱與釋出

Vue 之全域性事件匯流排和訊息訂閱與釋出

之前我們實現了子元件向父元件傳遞資料,很明顯,這是不夠的,看完這篇部落格,無論哪兩個元件之間傳遞和接收資料都沒有問題!

全域性事件匯流排(適用於任意元件間通訊) 原理:(看圖理解)

主要就是通過往 x 身上放事件,然後事件的回撥要放在想要獲取資料的元件身上,誰要傳資料就呼叫 x 身上對應的事件並往裡面存資料就可以了,相當於一箇中間商(哎,不得不說,它一出生就被利用了)

當然不是誰都能但此大任的,x 需要具備兩個條件:

  1. 所有元件都可以看到

  2. 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')
複製程式碼

使用事件匯流排:

  1. 接收資料:A 元件想接收資料,則在 A 元件中給 $bus 繫結自定義事件,事件的回撥留在 A 元件自身

mounted() { //或者後面指向的是一個方法,方法在 methods 裡面定義 //在全域性事件匯流排 bus中繫結一個hello事件,後面的回撥是箭頭函式,用於接收資料this.bus 中繫結一個 hello 事件,後面的回撥是箭頭函式,用於接收資料 this.bushello調this.bus.$on("hello", (value) => { console.log("我獲取到了資料", value); }); },

  1. 提供資料:

methods: { sentMyName(){ //在該方法中觸發 hello 這個事件,把資料傳過去 this.bus.bus.bus.emit('hello',this.myName) } }, 用這個方法的好處就是!我們就不需要再在標籤裡繫結自定義事件了,直接把事件在 $bus 裡建立,再在要傳資料的地方呼叫它就可以了!

當然還有個注意點,如果某個事件或繫結事件的元件你不用了,那要養成隨時解綁的好習慣!不要佔著空間不用,會導致空間浪費從而出現卡頓

最好在 beforeDestroy 鉤子中,用 $off 去解綁當前元件所用到的事件

在繫結事件的元件中解綁(即需要資料的元件)

beforeDestroy() { //解綁 bus中名為hello的事件this.bus 中 名為 hello 的事件 this.bushellothis.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 裡面建立的,不需要再匯入包

最後再分享一個方法: