用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)

當張三要離開時:

❌ 不是把「張三這個人」從公佈欄移除 ✅ 而是把「張三的電話號碼」從公佈欄撕掉

總結

移除監聽器」= 移除函數引用

「移除組件」= 銷毀整個實例

我們做的是前者,不是後者!