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

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

一開始的需求是這模樣的,我為了完成兩個頁面組件之間的數據通報,假定我有頁面A,點擊頁面A上的某一個按鈕今後,頁面會自動跳轉到頁面B,同時我願望將頁面A上的某一些參數照顧過去給頁面B。(我曉得,小參數的時刻能夠經由過程路由的params或許query去傳參數,或許大型數據能夠用vuex來處置懲罰,很遺憾我到現在還沒有做很大型的項目,所以還沒有效過vuex,接下來會進修一下。)

然後我就想,這不就是差別組件之間的數據通報題目罷了嗎?直接用bus
巴士事宜來通報數據不就行了嗎。因而,我就很愉快地舉行了。關於vue中的eventbus的運用,我之前在一篇vue中的數據通報中有提到過。 。

先給你們看一下我一開始的代碼:

完成目標: 點擊今後,bus emit事宜,然後趁便跳轉路由到/moneyRecord頁面。
接下來就是在MoneyRecord頁面中去on吸收這個事宜,然後接收參數。 // 這是頁面A的內部觸發bus事宜的代碼

 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,掌握台沒有輸出。然則當我第二次再點擊觸發事宜的時刻,就會輸出一個測試數據。再一次進去點擊,就輸出兩個數據。。。順次增添了。(掌握台上誰人“這是從上個頁面傳來的數據”就是測試數據)

所以,有兩個題目。

題目:

題目1: 為何第一次觸發的時刻頁面B中的on事宜沒有被觸發 題目2:
為何背面再一次順次去觸發的時刻會湧現,每一次都邑發明彷佛之前的on事宜分發都沒有被打消一樣,致使每一次的事宜觸發實行越來越多。 處理

針對題目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… 來源:簡書

    原文作者:a2774206
    原文地址: https://segmentfault.com/a/1190000014478413
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞