Vue3.0 項目中使用事件總線


vue2.x的項目里,通過 new 一個 Vue 實例的方式,讓它來充當事件總線,管理非父子組件之間的事件派發響應。

  1. 先創建一個eventHub.js文件,編輯如下
import Vue from "vue";
const eventHub = new Vue();
export default eventHub;
  1. 監聽事件的vue組件
import eventHub from "@/eventHub.js";

export default {
  name: '監聽事件的組件',
  created() {
    eventHub.$on("event-name", this.handler);
  },
  methods: {
    handler(params) {
    	console.log('event-name handler', params);
    },
  },
};
  1. 派發事件的vue組件
import eventHub from "@/eventHub.js";

export default {
  name: '派發事件的組件',
  Mounted() {
    eventHub.$emit("event-name", 'some params');
  },
};

Vue3.0 中取消 emit 的變動,使得沒法再按上面的方式使用了。官方建議使用第三方庫mitt

  1. 安裝
npm install --save mitt
  1. 注冊使用

創建一個eventHub.js文件

import Mitt from 'mitt'

const eventHub = new Mitt();

eventHub.$on = eventHub.on;
eventHub.$off = eventHub.off;
eventHub.$emit = eventHub.emit;

export default eventHub;
  1. 將事件總線注冊到 Vue 實例
    main.js
import {createApp} from 'vue'
import App from "./App.vue"
import eventHub from '@/plugins/eventHub.js';

const app = createApp(App);

// 配置全局事件總線
app.config.globalProperties.eventHub = eventHub;

app.mount('#app');
  1. 監聽事件的組件
import { getCurrentInstance, onMounted } from 'vue';

export default {
  name: 'YourComponent',
  setup() {
    const eventHandler = async (params) => {
      // some async process
    };

    const { eventHub } = getCurrentInstance().proxy;
    eventHub.$on('event-name', eventHandler);

    onBeforeUnmount(() => {
      eventHub.$off('event-name', eventHandler);
    });
  },
};
  1. 派發事件的組件
import { getCurrentInstance, onMounted } from 'vue';

export default {
  name: '',
  setup() {
    const { eventHub } = getCurrentInstance().proxy;
    
    onMounted(() => {
      eventHub.$emit('event-name', 'some params');
    });
  },
};

注:

  • 上面封裝的時候,使用$emit / $on / $off,是為了方便 Vue2.x的項目做遷移
  • 注意監聽要在派發之前,Vue3.0中生命周期的調用順序要清楚

動動小手,簡單實現一個上面的mitt工具類。

class EventHub {
  constructor() {
    this.pool = {}
  }

  $on(event, handler) {
    this.pool[event] = this.pool[event] || new Set();

    this.pool[event].add(handler);
  }

  $off(event, handler) {
    this.pool[event].delete(handler);
  }

  $emit(event, params) {
    const handlers = this.pool[event];
    if (!handlers || !handlers.size) return;
    handlers.forEach(fn => {
      fn(params);
    })
  }

  $clear(event) {
    this.pool[event] = undefined;
  }

  $clearAll() {
    this.pool = {};
  }

}

const eventHub = new EventHub();

export default eventHub;

使用方式與上方一致,代碼無需改動,效果無異。

問:如果再要實現一個$once呢?聰明的你來實現一下吧。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM