vue非父子組件通訊中eventbus被屢次觸發(vue中使用eventbus踩過的坑)

轉載於簡書 原文連接: https://www.jianshu.com/p/fde...

一開始的需求是這樣子的,我爲了實現兩個頁面組件之間的數據傳遞,假設我有頁面A,點擊頁面A上的某一個按鈕以後,頁面會自動跳轉到頁面B,同時我但願將頁面A上的某一些參數攜帶過去給頁面B。(我知道,小參數的時候能夠經過路由的params或者query去傳參數,或者大型數據能夠用vuex來處理,很遺憾我到如今尚未作很大型的項目,因此尚未用過vuex,接下來會學習一下。)vue

而後我就想,這不就是不一樣組件之間的數據傳遞問題而已嗎?直接用bus
巴士事件來傳遞數據不就好了嗎。因而,我就很愉快地進行了。關於vue中的eventbus的使用,我以前在一篇vue中的數據傳遞中有提到過。 。git

先給大家看一下我一開始的代碼:github

實現目標: 點擊以後,bus emit事件,而後順便跳轉路由到/moneyRecord頁面。
接下來就是在MoneyRecord頁面中去on接收這個事件,而後接受參數。 // 這是頁面A的內部觸發bus事件的代碼vuex

editList (index, date, item) {
//  點擊進入編輯的頁面,須要傳遞的參數比較多。
  console.log(index, date, item)
  bus.$emit('get', {
    item: item.type,
    date: date
  })
  this.$router.replace({path: '/moneyRecord'})
}

// moneyRecord頁面
created () {
    //這裏我將icon的list給保存下來了
    bus.$on('get', this.myhandle)
  },
methods: {
  myhandle (val) {
      console.log(val, '這是從上個頁面傳遞過來的參數')
    }
}
就當我欣喜若狂的時候,以爲本身只要在頁面A觸發了get事件,頁面B中就會理所固然的接受了數據。然而,結果卻不如人意,看一下下面的動圖。

主要是看「」這是從上個頁面傳來的數據這一行數據的輸出次數狀況來判斷事件觸發次數。「」學習

test.gif
不知道你有沒有發現,就是我第一次進去list頁面的時候,我隨便點擊一下list下的任何一個item,控制檯沒有輸出。可是當我第二次再點擊觸發事件的時候,就會輸出一個測試數據。再一次進去點擊,就輸出兩個數據。。。依次增長了。(控制檯上那個「這是從上個頁面傳來的數據」就是測試數據)測試

因此,有兩個問題。this

問題:code

問題1: 爲何第一次觸發的時候頁面B中的on事件沒有被觸發 問題2:
爲何後面再一次依次去觸發的時候會出現,每一次都會發現好像以前的on事件分發都沒有被撤銷同樣,致使每一次的事件觸發執行愈來愈多。 解決router

針對問題1
這個還得從vue的生命週期提及了,我先進行了測試,就是當從頁面組件A跳轉到頁面組件B的時候,兩個組件的生命週期分別是怎麼樣的,關於vue的生命週期具體每個時期作什麼事情我就再也不贅述了,下面po一張vue生命週期的圖。生命週期

image.png 我本身作了實驗來驗證,這個頁面跳轉過程當中,這兩個組件的生命週期的執行狀況。

// 我分別在頁面A和頁面B中去添加如下代碼:
beforeCreate () {
   console.group('%c%s', 'color:red', 'beforeCreate 建立前狀態===============組件2》')
 },
 created () {
   console.group('%c%s', 'color:red', 'created 建立完畢狀態===============組件2》')
 },
 beforeMount () {
   console.group('%c%s', 'color:red', 'beforeMount 掛載前狀態===============組件2》')
 },
 mounted () {
   console.group('%c%s', 'color:red', 'mounted 掛載狀態===============組件2》')
 },
 beforeUpdate () {
   console.group('%c%s', 'color:red', 'beforeUpdate 更新前狀態===============組件2》')
 },
 updated () {
   console.group('%c%s', 'color:red', 'updated 更新狀態===============組件2》')
 },
 beforeDestroy () {
   console.group('%c%s', 'color:red', 'beforeDestroy 破前狀態===============組件2》')
 },
 destroyed () {
   console.group('%c%s', 'color:red', 'destroyed 破壞狀態===============組件2》')
 }

// 另一個組件的我就不放出來了

測試結果圖:

test.gif
image.png
其實,能夠經過結果清楚看到,當咱們還在頁面A的時候,頁面B還沒生成,也就是頁面B中的 created中所監聽的來自於A中的事件尚未被觸發。這個時候當你A中emit事件的時候,B實際上是沒有監聽到的。

再看一下,紅色的是B頁面組件,當你從頁面A到頁面B跳轉的時候,發生了什麼?首先是先B組件先created而後beforeMount接着A組件才被銷燬,A組件才執行beforeDestory,以及destoryed.

因此,咱們能夠把A頁面組件中的emit事件寫在beforeDestory中去。由於這個時候,B頁面組件已經被created了,也就是咱們寫的$on事件已經觸發了

因此能夠,在beforeDestory的時候,$emit事件。

// 修改一下A頁面中的代碼:
// 這是原先的代碼
  editList (index, date, item) {
//  點擊進入編輯的頁面,須要傳遞的參數比較多。
      console.log(index, date, item)
      this.item = item.type
      this.date = date
      this.$router.replace({path: '/moneyRecord'})
    }
// 從新在data屬性內部定義新的變量,來存儲要傳過去的數據;

而後:

beforeDestroy () {
 console.log(this.highlight, '這是今年的數據', this, '看看組件銷燬以前會發生什麼')
 bus.$emit('get', {
        item: this.item,
        date: this.date
      })
 },
接下來。看一下修改以後的效果

test.gif
能夠看到,就是第一次點擊list的時候,也就是第一次觸發emit事件的時候,控制太就輸出了,因此在beforeDestoryed去$emit是起到做用的,B頁面組件也監聽$on到了。

可是,好像,就是事件的觸發仍是會依次增長,就是控制檯的輸出每次都有所增長了。。。

解決: 看一下github上提出的。issue https://github.com/vuejs/vue/...

image.png 尤大大提出瞭如下解決:

image.png
就是說,這個$on事件是不會自動清楚銷燬的,須要咱們手動來銷燬。(不過我不太清楚這裏的external bus 是什麼意思,有大神能解答一下的嗎,尤大大也提到若是是註冊的是external bus 的時候須要清除)*

因此。我在B組件頁面中添加Bus.$off來關閉。代碼以下:

// 在B組件頁面中添加如下語句,在組件beforeDestory的時候銷燬。

beforeDestroy () {
    bus.$off('get', this.myhandle)
  },
來看一下輸出的結果

t能夠看到,控制檯第一次進去的時候就有輸出,並且輸出的不會逐次增長
*固然,尤大大還說能夠寫一個mixin?我還不知道是什麼?之後在研究一下。

總結: 因此,若是想要用bus
來進行頁面組件之間的數據傳遞,須要注意亮點,組件A$emit事件應在beforeDestory生命週期內。其次,組件B內的$on記得要銷燬。

提問時間:大家在實現頁面組件之間的數據傳遞有什麼好的方法嗎?能夠留言分享一下嗎?有時候雖然也能夠經過從後臺獲取,可是考慮到數據只有幾個須要傳的話,就沒有必要去請求數據,我知道有的還有用vueX傳遞。還有呢?

做者:Katherine的小世界 連接:https://www.jianshu.com/p/fde... 來源:簡書

相關文章
相關標籤/搜索