前段時間,同事發現一個彈窗組件被多個頁面複用,而後點擊按鈕出現了屢次響應。明明頁面都會被銷燬掉的呀,爲啥還會出現重複調用呢。html
其實之前我也碰到過一兩次,不知道啥狀況後來沒有再復現,再加上工期緊,當時就沒有引發重視。此次同事碰到了,屢次試驗復現了。才深知當時挖的大坑啊沒有填。vue
因此此次就單獨弄了個demo專門復現並解決這個問題。也但願吸收教訓,之後碰到問題都要記錄下來,儘早早早早早解決啊,否則都是坑。git
另外,文章裏的關於父子組件的全局事件監聽是錯誤的選擇,請你們不要使用這種。(可是兄弟組件能夠用文中這種全局監聽的方式)
請用官方例子(遇到問題,請多用官方,否則直接參考其餘同窗的思路極可能挖坑。這裏是之前直接搜索到eventbus的實現方式,請引覺得戒,哈哈,我就作個反面教材吧
傳送門在此github
首先我寫了一個dialogx的小組件,裏面只有一個點擊按鈕。當點擊的時候,會觸發一個btnClick
的事件。數組
而後我又寫了兩個頁面用來測試重複響應。下面是 test1.vue
,至於test2
也同樣,就不從新放圖了。ide
而後,我們來點點點點點點!就能發現,在test2
頁面發起的事件,而test1
也響應了,這屬於重複響應是不符合咱們的項目須要的。測試
這...是咋回事~~??ui
通過查詢相關資料,肯定了問題在於沒有過去的銷燬事件響應。this
好,咱們出發去加上銷燬邏輯。spa
因而我在dialogx.vue
中加入如下代碼,在路由切換組件被銷燬的時候,對btnClick
事件進行銷燬。順便打印一下 this.$root
看看裏面是個啥結構。
而後就有了如下的操做,竟然...竟然 test2.vue 無法響應了。WTF,這又是啥狀況。
冷靜下來,好好分析。首先這種狀況是由於咱們加了銷燬操做致使的,因此確定是銷燬的問題。
那麼咱們繼續追蹤。發現路由切換的各類操做的順序是這樣的。
這說明 什麼問題?
新頁面的
created
先執行,而後開始逐漸銷燬老頁面。仔細看看,咱們能發現問題,test2.vue
在建立監聽事件的時候,是在dialogx.vue
銷燬以前的。人家剛建立好監聽事件,因爲執行順序問題,被子組件給清除了,因此test2.vue
在點擊發射時,是攔截不到的。
好,既然由於執行順序的問題,那咱們把監聽事件註冊放在 mounted
裏。
果真,成功了。
對於事件的觸發和監聽,由於咱們這是用 eventbus
實現的。爲了看看裏面具體是爲何,因而我打印了 this.$root
看看更細節的是爲何。
首先,每一次監聽 this.$root.$on('btnClick')
都是一次事件註冊,而後我在打印的結果裏,找到了如下內容。
btnClick
是一個數組,這就意味着每一次btnClick
事件註冊,都是往裏存一個處理方法。
而後爲了驗證個人想法,我把 test2.vue
中的監聽事件去了,直接看咱們的 $off
效果。
是 null
,這就解釋了爲何,剛纔監聽事件寫在 created
裏,爲何不生效了,由於整個事件都被設置爲 null
了。
爲了達到組件複用不產生重複響應的問題。咱們能夠以下作。
1.在子組件裏的
destroyed
方法裏,對事件進行銷燬操做($off)
2.在頁面中mounted
方法中進行事件監聽。
GitHub代碼地址:https://github.com/XuXiaoGH/v...
此次是一次異常排查過程的記錄,若是對你有些許幫助,不妨收藏點個贊,這將是我繼續的很大動力。
ps: GIF截圖軟件是 LICEcap ,很是好用,推薦一下。