最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue消息訂閱與發(fā)布過程

 更新時間:2025年11月03日 09:54:26   作者:咖啡の貓  
發(fā)布-訂閱模式是一種設(shè)計模式,通過事件中心實現(xiàn)對象間的解耦通信,在Vue中,Vue2使用Vue實例作為事件總線,Vue3推薦使用mitt庫,發(fā)布-訂閱模式適用于廣播通知、解耦組件和復(fù)雜狀態(tài)管理,在選擇工具時,建議根據(jù)場景選擇合適的工具

一、什么是發(fā)布-訂閱模式?

發(fā)布-訂閱模式 是一種對象間通信的設(shè)計模式,包含三個核心角色:

  • 發(fā)布者(Publisher):發(fā)出消息(事件)
  • 訂閱者(Subscriber):監(jiān)聽并處理消息
  • 事件中心(Event Channel):中介,負責消息的注冊與分發(fā)

類比理解

想象一個“廣播電臺”:

  • 電臺(事件中心)負責廣播
  • 主持人(發(fā)布者)說:“現(xiàn)在是北京時間 8 點整”
  • 聽眾(訂閱者)聽到后,各自執(zhí)行動作(起床、煮咖啡、打卡)

發(fā)布者無需知道誰在聽,訂閱者也無需知道誰在說,實現(xiàn)解耦。

二、核心概念:訂閱、發(fā)布、取消訂閱

操作方法說明
訂閱on(event, callback)注冊事件監(jiān)聽器
發(fā)布emit(event, ...args)觸發(fā)事件,傳遞數(shù)據(jù)
取消訂閱off(event, callback)移除監(jiān)聽,防止內(nèi)存泄漏

三、在 Vue 中的實現(xiàn)方式

1. Vue 2:使用 Vue 實例作為事件總線

Vue 2 的實例本身實現(xiàn)了事件接口($on$emit、$off),可直接用作事件中心。

(1) 創(chuàng)建 EventBus

// utils/eventBus.js
import Vue from 'vue'

// 創(chuàng)建一個 Vue 實例作為全局事件中心
const EventBus = new Vue()

export default EventBus

(2) 訂閱消息(在組件中)

<!-- NotificationBar.vue -->
<script>
import EventBus from '@/utils/eventBus'

export default {
  data() {
    return {
      message: ''
    }
  },
  created() {
    // 訂閱 'show-notification' 事件
    EventBus.$on('show-notification', (msg, type) => {
      this.message = `[${type}] ${msg}`
      this.show()
    })
  },
  beforeDestroy() {
    // 組件銷毀時取消訂閱,避免內(nèi)存泄漏
    EventBus.$off('show-notification')
  },
  methods: {
    show() {
      // 顯示通知
      console.log(this.message)
    }
  }
}
</script>

(3) 發(fā)布消息

<!-- LoginButton.vue -->
<script>
import EventBus from '@/utils/eventBus'

export default {
  methods: {
    login() {
      // 發(fā)布登錄成功事件
      EventBus.$emit('user-logged-in', { id: 1, name: 'Alice' })
      
      // 發(fā)布全局通知
      EventBus.$emit('show-notification', '登錄成功!', 'success')
    }
  }
}
</script>

實現(xiàn)了跨組件通信,但需手動管理生命周期。

2. Vue 3:使用mitt庫(推薦)

Vue 3 移除了實例上的 $on、$off 方法,因此不能再使用 Vue 實例作為事件總線。

(1) 安裝 mitt

npm install mitt

mitt 是一個超輕量(<200B)的事件發(fā)射器,API 簡潔,完美替代。

(2) 創(chuàng)建全局事件中心

// utils/eventBus.js
import mitt from 'mitt'

// 創(chuàng)建事件中心
const EventBus = mitt()

export default EventBus

(3) 在 Vue 3 組件中使用

<!-- NotificationBar.vue -->
<script setup>
import { onMounted, onUnmounted } from 'vue'
import EventBus from '@/utils/eventBus'

// 訂閱事件
const handleNotification = (data) => {
  console.log(`[通知] ${data.type}: ${data.msg}`)
}

onMounted(() => {
  EventBus.on('show-notification', handleNotification)
})

// 取消訂閱
onUnmounted(() => {
  EventBus.off('show-notification', handleNotification)
})
</script>
<!-- LoginButton.vue -->
<script setup>
import EventBus from '@/utils/eventBus'

function login() {
  // 發(fā)布事件
  EventBus.emit('user-logged-in', { id: 1, name: 'Bob' })
  EventBus.emit('show-notification', {
    msg: '登錄成功!',
    type: 'success'
  })
}
</script>

<template>
  <button @click="login">登錄</button>
</template>

mitt 支持 TypeScript,API 簡潔:on、emit、off、clear。

四、手寫一個簡易的 Event Hub

為了理解原理,我們來實現(xiàn)一個極簡版的事件中心:

// utils/EventHub.js
class EventHub {
  constructor() {
    this.events = {}
  }

  // 訂閱
  on(event, callback) {
    if (!this.events[event]) {
      this.events[event] = []
    }
    this.events[event].push(callback)
  }

  // 發(fā)布
  emit(event, ...args) {
    if (this.events[event]) {
      this.events[event].forEach(callback => callback(...args))
    }
  }

  // 取消訂閱
  off(event, callback) {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter(cb => cb !== callback)
    }
  }

  // 清除所有
  clear(event) {
    if (event) {
      delete this.events[event]
    } else {
      this.events = {}
    }
  }
}

export default new EventHub()

核心就是維護一個事件-回調(diào)函數(shù)的映射表。

五、發(fā)布-訂閱 vs 其他通信方式

通信方式方向耦合度適用場景
發(fā)布-訂閱任意廣播通知、解耦組件
props / emit父↔子緊密相關(guān)的父子組件
Pinia任意共享狀態(tài)、復(fù)雜邏輯
Provide/Inject祖→孫主題、配置傳遞

選擇建議:

  • 狀態(tài)共享 → Pinia
  • 簡單通知 → mitt
  • 祖先傳值 → provide/inject

六、最佳實踐與注意事項

1. 使用語義化事件名

// ? 避免模糊命名
EventBus.emit('click')

// ? 使用前綴和語義化命名
EventBus.emit('user:login-success', user)
EventBus.emit('cart:item-added', item)

2. 務(wù)必取消訂閱

// Vue 2
beforeDestroy() {
  EventBus.$off('event-name')
}

// Vue 3 Composition API
onUnmounted(() => {
  EventBus.off('event-name', handler)
})

忘記 off 會導(dǎo)致內(nèi)存泄漏重復(fù)觸發(fā)。

3. 避免過度使用

  • 不要用事件總線代替狀態(tài)管理
  • 復(fù)雜狀態(tài)同步 → 使用 Pinia
  • 事件過多 → 考慮模塊化事件中心

4. TypeScript 支持

// types/events.ts
type Events = {
  'user:login': (user: User) => void
  'cart:update': (count: number) => void
  'app:loading': (status: boolean) => void
}

// utils/eventBus.ts
import mitt from 'mitt'
export const useEventBus = () => mitt<Events>()

類型安全,IDE 自動提示。

七、現(xiàn)代替代方案:Pinia + Actions

對于大多數(shù)場景,Pinia 是更優(yōu)解:

// stores/appStore.ts
import { defineStore } from 'pinia'

export const useAppStore = defineStore('app', {
  state: () => ({
    user: null,
    cartCount: 0,
    isLoading: false
  }),
  actions: {
    login(user) {
      this.user = user
      // 其他組件自動響應(yīng)
    },
    addToCart(item) {
      this.cartCount++
    },
    setLoading(status) {
      this.isLoading = status
    }
  }
})
<!-- 任何組件 -->
<script setup>
import { useAppStore } from '@/stores/appStore'

const appStore = useAppStore()

// 直接調(diào)用 action
appStore.login(userData)
</script>

響應(yīng)式、可調(diào)試、支持 SSR。

八、總結(jié)

核心點說明
本質(zhì)解耦的事件驅(qū)動通信
角色發(fā)布者、訂閱者、事件中心
Vue 2new Vue() 作為 EventBus
Vue 3使用 mitt 庫
優(yōu)點靈活、解耦、輕量
缺點難以追蹤、易內(nèi)存泄漏
推薦簡單通知用 mitt,狀態(tài)用 Pinia

一句話總結(jié):

發(fā)布-訂閱是“消息廣播”,而 Pinia 是“狀態(tài)中心”——根據(jù)場景選擇合適的工具。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Vue3中pinia用法示例

    Vue3中pinia用法示例

    這篇文章主要介紹了Vue3中使用pinia,本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • VUE使用 wx-open-launch-app 組件開發(fā)微信打開APP功能

    VUE使用 wx-open-launch-app 組件開發(fā)微信打開APP功能

    這篇文章主要介紹了VUE使用 wx-open-launch-app 組件開發(fā)微信打開APP功能,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • vue使用codemirror的兩種用法

    vue使用codemirror的兩種用法

    這篇文章主要介紹了在vue里使用codemirror的兩種用法,每種方法通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-08-08
  • Element中Slider滑塊的具體使用

    Element中Slider滑塊的具體使用

    這篇文章主要介紹了Element中Slider滑塊的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Vue中引入swiper報錯的問題及解決

    Vue中引入swiper報錯的問題及解決

    這篇文章主要介紹了Vue中引入swiper報錯的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • vue中v-for 循環(huán)對象中的屬性

    vue中v-for 循環(huán)對象中的屬性

    這篇文章主要介紹了 vue中v-for 循環(huán)對象中的屬性,文章圍繞v-for 循環(huán)對象的相關(guān)資料展開詳細內(nèi)容,需要的朋友可以參考一下,希望對大家有所幫助
    2021-11-11
  • Vue循環(huán)中多個input綁定指定v-model實例

    Vue循環(huán)中多個input綁定指定v-model實例

    這篇文章主要介紹了Vue循環(huán)中多個input綁定指定v-model實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • vue-router的使用方法及含參數(shù)的配置方法

    vue-router的使用方法及含參數(shù)的配置方法

    這篇文章主要介紹了vue-router的使用方法及含參數(shù)的配置方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-11-11
  • 詳解vuex的簡單使用

    詳解vuex的簡單使用

    這篇文章主要介紹了詳解vuex的簡單使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • vue3中v-model的用法詳解

    vue3中v-model的用法詳解

    vue 提供了很多自定義指令,大大方便了我們的開發(fā),其中最常用的也就是 v-model,他可以在組件上使用以實現(xiàn)雙向綁定。它可以綁定多種數(shù)據(jù)結(jié)構(gòu), 今天總結(jié)一下用法
    2023-04-04

最新評論

南充市| 桂林市| 柳州市| 绥中县| 平原县| 全南县| 颍上县| 桑植县| 广宁县| 孟津县| 灵璧县| 曲周县| 剑川县| 白朗县| 水城县| 渑池县| 乐亭县| 毕节市| 保靖县| 鄂伦春自治旗| 彭州市| 宁津县| 尚义县| 江安县| 怀宁县| 平利县| 博爱县| 梁河县| 土默特右旗| 金昌市| 建德市| 高要市| 景宁| 新宁县| 深水埗区| 英超| 星子县| 织金县| 托里县| 大冶市| 万源市|