1. 程式人生 > >vue中eventbus被多次觸發(vue中使用eventbus踩過的坑)

vue中eventbus被多次觸發(vue中使用eventbus踩過的坑)

一開始的需求是這樣子的,我為了實現兩個頁面元件之間的資料傳遞,假設我有頁面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到了。

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

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/fde85549e3b0
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。

相關推薦

vueeventbus觸發vue使用eventbus【bus.$on事件繫結】

  問題描述:只要頁面沒有強制重新整理,存在元件切換,bus.$on方法會被多次繫結,造成事件多次觸發   觸發bus.$on中繫結的方法.png

vueeventbus觸發vue使用eventbus

一開始的需求是這樣子的,我為了實現兩個頁面元件之間的資料傳遞,假設我有頁面A,點選頁面A上的某一個按鈕之後,頁面會自動跳轉到頁面B,同時我希望將頁面A上的某一些引數攜帶過去給頁面B。(我知道,小引數的時候可以通過路由的params或者query去傳引數,或者大型資料可以用v

Android 監聽廣播autoLauch 防止啟動頁面啟動筆記

直接上程式碼: 1.監聽USB插入的廣播,這個廣播自己插入android收usb是觸發,當然我是監聽自定義廣播。 看下面manifest 配置,: <?xml version="1.0" e

EPOLLONESHOT及其引發的EPOLL在ET能觸發嗎?

以下是《Linux高效能伺服器程式設計》對EPOLLONESHOT的描述: 對於註冊了EPOLLONESHOT的檔案描述符,作業系統最多觸發其上註冊的一個可讀、可寫或者異常的事件,且只觸發一次,除非我們使用epoll_ctl函式重置該檔案描述符上註冊的EPOLLONE

27.Spring-Boot攔截器靜態資源的處理以及Spring mvc configuring拓展介紹

一.springboot中對靜態資源的處理  預設情況下,springboot提供存放放置靜態資源的資料夾:  /static  /public   /resources  /META-INF/resources 對於maven專案即就是存在src/main/re

Vue事件總線eventBus$on()會觸發解決辦法

off cti UNC 關於 span sea col on() for 項目中使用了事件總線eventBus來進行兩個組件間的通信, 使用方法是是建立eventBus.js文件,暴露一個空的Vue實例,如下: import Vue from ‘vue‘export de

springMVC的controllerinsert(),記優惠券領取

校驗 syn https gmv list spring 源代碼 null tro 做活動,要發優惠券,規定一人只能領取一次(一張)。一天下來發現有一個客戶領到了4張,且是同一秒生成的,源代碼如下: 估計多個線程同時進了add方法。 想到了單例的雙重校驗,現修改代碼如

jqueryclick點選事件巢狀後觸發的解決方案

首先講講我遇到這個問題的時候,我最開始想到的是阻止事件冒泡,想了一下好像沒有什麼關係的,最後決定還是動手做做看,放到專案中試了試確實是沒有什麼關係的,傻眼了怎麼辦,來講講我的親身體驗吧! 產生此種小姑的原因:jQuery中的click事件會累計繫結,所以我們可以在下次點

函式放在標頭檔案包含的重定義問題

Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 轉載請標明來源 例如一個頭檔案headfile.h這樣寫 #pragma once bool Func (){return true;} 在這個標頭檔案被多個地方包含的時候就會出

JavaScriptmouseover和mouseout觸發解決辦法

問題描述 我希望當滑鼠移動到id1上的時候,id2顯示,當滑鼠離開id1的時候,id2顯示。問題如下:  1.當滑鼠從id1上移動到id2上的時候,id由有顯示變為不顯示,然後變為顯示  2.當滑鼠從id2上移動到id1上的時候, id2有顯示變為不顯示,然後變為顯示  我希望的是當滑鼠在id1或者id2

讓程序不重複執行linux程式設計小技巧

---讓程式不能被多次執行 ---問題 (1)因為守護程序是長時間執行而不退出,因此./a.out執行一次就有一個程序,執行多次就有多個程序。 (2)這樣並不是我們想要的。我們守護程序一般都是伺服器,伺服器程式只要執行一個就夠了,多次同時執行並沒有意義甚至會帶來錯誤。 (3

uni-app使用scroll-view滾到底部時觸發scrolltolower

一、前言、scroll-view基本屬性: 前言:   前段時間使用scroll-view可滾動檢視區域容器來做多個不同內容的展示(在我這個頁面中同時使用了三個scroll-view做資料展示),因為這幾個展示的內容的資料都比較的多,因此為了頁面的資料載入順暢決定使用上拉載入(簡單的說就是資料分頁顯示)。 頁

Ubuntu 16.04下使用gcc輸出匯編的.0文件為可執行文件時出現:`_start'定義

file blank pan art 一次 x86_64 另一個 使用 urn 錯誤如下: `_start‘被多次定義 /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.text+0

jq:mouseover和mouseout觸發解決辦法

mouseover ren div clas 結構 tro 需要 als ldr 區別: mouseover與mouseenter   不論鼠標指針穿過被選元素或其子元素,都會觸發 mouseover 事件。   只有在鼠標指針穿過被選元素時,才會觸發 mouseenter

在一個網頁是可以引用自定義字體的

image 分享 images 一個 .com 自定義 alt img es2017 在一個網頁中是可以多次引用自定義字體的

Vue--axios:vue的ajax異步請求發送和請求數據

lan his src 操作 ajax請求 itl func gin 出錯 一.使用axios發送get請求 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <me

一個php腳本執行實例PDO,會建立次數據庫連接。

重用 slist OS play 類實例化 每次 連接 inf log 腳本代碼: <?php try { $dbh = new PDO(‘mysql:host=localhost;dbname=test‘, ‘root‘, ‘root‘); } ca

Javascript知識匯總------js容易忽略的細節持續更新

bsp true 方式 efi 定義 沒有 快捷 快捷方式 == in運算符     語法:boolean “name” in Object 判斷對象是否具有某一個屬性 var myObject

即時搜索:對於ios自帶輸入法輸入中文時觸發input事件的處理

rip input事件 由於 了解 end 處理 移動 ref 使用 實現移動端的即時搜索的最佳方案,一定是使用input propertychange事件了,但是在ios設備上遇到了問題,使用ios自帶輸入法輸入漢字時,會出現多次觸發input事件的情況,一開始可能由於搜

centos7keeplived代碼隨記虛擬機做的真的練吧

備份服務器 ash ipv4 pts firefox keepal live 功能 arp 調度服務器地址192.168.100.100節點1 192.168.100.110節點2 192.168.100.120 -------------------------DR調度服