用eventBus傳資料 - daniel-qa/Vue GitHub Wiki
用eventBus傳資料
P.S 只有 on 的地方,才需要 off 監聽器,多加的話,會造成收不到 evnet ( 因為被註銷掉了)
- event 傳資料
// 將 teachersQuotaData 通過 EventBus 傳遞給 HiTeachQuotaOverview.vue
if (this.$EventBus) {
this.$EventBus.$emit('update-teachers-quota-data', this.teachersQuotaData);
}
- 監聽 event 收資料
// 監聽 EventBus 事件,接收從 Product.vue 傳來的 teachersQuotaData
if (this.$EventBus) {
this.$EventBus.$on('update-teachers-quota-data', (data) => {
console.log('接收到 teachersQuotaData:', data);
this.quotaData = data;
});
}
// 如果沒有 quotaData,則呼叫 API 獲取
if (!this.quotaData) {
this.getTeachersQuota(); // 取得授權服務(service), 和授權教師(techers)
}
- 清理 EventBus 監聽器
beforeDestroy() {
// 注銷 EventBus 的事件監聽器,防止記憶體洩漏
if (this.$EventBus) {
this.$EventBus.$off('switch-to-quota-tab', this.handleQuotaTab)
this.$EventBus.$off('switch-to-auth-overview-tab', this.handleAuthOverview)
this.$EventBus.$off('update-quota-data', this.handleUpdateQuotaData)
}
}
不清理事件監聽器的影響
🎯 功能不會壞 - 最新的監聽器會正常執行
💥 但會有錯誤 - 失效的監聽器會報錯
🐌 性能浪費 - 執行無用的函數調用
📱 調試困難 - 錯誤訊息會混淆真正的問題
還是會被處理,但會也會產生報錯
這正是為什麼 beforeDestroy() 清理監聽器如此重要:
不是為了修復功能(功能本來就正常) 而是為了避免無謂的錯誤和性能浪費
- 我們移除的不是「組件」,而是「事件監聽器」(Event Listener)
註冊監聽器時:
created() {
// 把處理函數「掛」到 EventBus 上
this.$EventBus.$on('switch-to-quota-tab', this.handleQuotaTab)
}
// EventBus 內部變成:
// events: {
// 'switch-to-quota-tab': [this.handleQuotaTab] ← 新增了這個函數
// }
移除監聽器時:
beforeDestroy() {
// 把處理函數「從」EventBus 上移除
this.$EventBus.$off('switch-to-quota-tab', this.handleQuotaTab)
}
// EventBus 內部變成:
// events: {
// 'switch-to-quota-tab': [] ← 函數被移除了
// }
為什麼這個區別很重要?
1. 技術準確性
// 組件 = 整個 Vue 實例 + 模板 + 數據 + 方法
// 監聽器 = 只是其中一個小小的函數引用
2. 理解記憶體洩漏的原因
// 組件銷毀了,但 EventBus 仍然持有:
this.$EventBus.events['switch-to-quota-tab'] = [
this.handleQuotaTab // ← 這個函數引用還在!
]
// 因為這個函數是組件實例的方法
// 所以整個組件實例無法被垃圾回收
3. 除錯時的思考方式
// 如果出現重複觸發問題
// 你會檢查:「是不是有多個監聽器函數?」
// 而不是:「是不是有多個組件?」
類比說明
想像 EventBus 是一個公佈欄:
公佈欄(EventBus)
├── 「配額管理」通知欄
│ ├── 張三的電話號碼 (監聽器1)
│ └── 李四的電話號碼 (監聽器2)
└── 「授權一覽」通知欄
└── 王五的電話號碼 (監聽器3)
當張三要離開時:
❌ 不是把「張三這個人」從公佈欄移除 ✅ 而是把「張三的電話號碼」從公佈欄撕掉
總結
移除監聽器」= 移除函數引用
「移除組件」= 銷毀整個實例
我們做的是前者,不是後者!