Vue.js 3 事件总线

新手上路,请多包涵

如何在 Vue 3 中创建事件总线?


在 Vue 2 中,它是:

 export const bus = new Vue();

 bus.$on(...)
bus.$emit(...)


In Vue 3, Vue is not a constructor anymore, and Vue.createApp({}); returns an object that has no $on and $emit methods.

原文由 KeyKi 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 658
2 个回答

正如官方 文档 中所建议的,您可以使用 mitt 库在组件之间调度事件,假设我们有一个侧边栏和 header 包含一个关闭/打开侧边栏的按钮,我们需要该按钮来切换某些属性在侧边栏组件内部:

在 main.js 中导入该库并创建该发射器的实例并定义为 全局属性

安装 :

 npm install --save mitt

用法 :

 import { createApp } from 'vue'
import App from './App.vue'
import mitt from 'mitt';
const emitter = mitt();
const app = createApp(App);
app.config.globalProperties.emitter = emitter;
app.mount('#app');

在标头中发出带有一些有效负载的 toggle-sidebar 事件:

 <template>
  <header>
    <button @click="toggleSidebar"/>toggle</button>
  </header>
</template>
<script >
export default {
  data() {
    return {
      sidebarOpen: true
    };
  },
  methods: {
    toggleSidebar() {
      this.sidebarOpen = !this.sidebarOpen;
      this.emitter.emit("toggle-sidebar", this.sidebarOpen);
    }
  }
};
</script>

在侧边栏中接收带有有效负载的事件:

 <template>
  <aside class="sidebar" :class="{'sidebar--toggled': !isOpen}">
  ....
  </aside>
</template>
<script>
export default {
  name: "sidebar",
  data() {
    return {
      isOpen: true
    };
  },
  mounted() {
    this.emitter.on("toggle-sidebar", isOpen => {
      this.isOpen = isOpen;
    });
  }
};
</script>

对于那些使用 composition api 的人,他们可以使用 emitter 如下:

创建一个文件 src/composables/useEmitter.js

 import { getCurrentInstance } from 'vue'

export default function useEmitter() {
    const internalInstance = getCurrentInstance();
    const emitter = internalInstance.appContext.config.globalProperties.emitter;

    return emitter;
}

从那里您可以使用 useEmitter 就像使用 useRouter 一样:

 import useEmitter from '@/composables/useEmitter'

export default {
  setup() {
    const emitter = useEmitter()
    ...
  }
  ...
}

使用组合 API

您还可以从新的组合 API 中受益并定义一个可组合的事件总线:

事件总线.js

 import { ref } from "vue";
const bus = ref(new Map());

export default function useEventsBus(){

    function emit(event, ...args) {
        bus.value.set(event, args);
    }

    return {
        emit,
        bus
    }
}

在组件 A 中:

 import useEventsBus from './eventBus';
...
//in script setup or inside the setup hook
const {emit}=useEventsBus()
...
 emit('sidebarCollapsed',val)

在组件 B 中:

 const { bus } = useEventsBus()

watch(()=>bus.value.get('sidebarCollapsed'), (val) => {
  // destruct the parameters
    const [sidebarCollapsedBus] = val ?? []
    sidebarCollapsed.value = sidebarCollapsedBus
})

原文由 Boussadjra Brahim 发布,翻译遵循 CC BY-SA 4.0 许可协议

在 Vue.js 的第 3 版上,您可以使用第三方库,也可以使用以发布者-订阅者(PubSub 概念)编程模式编写的功能。

事件.js

 //events - a super-basic Javascript (publish subscribe) pattern

class Event{
    constructor(){
        this.events = {};
    }

    on(eventName, fn) {
        this.events[eventName] = this.events[eventName] || [];
        this.events[eventName].push(fn);
    }

    off(eventName, fn) {
        if (this.events[eventName]) {
            for (var i = 0; i < this.events[eventName].length; i++) {
                if (this.events[eventName][i] === fn) {
                    this.events[eventName].splice(i, 1);
                    break;
                }
            };
        }
    }

    trigger(eventName, data) {
        if (this.events[eventName]) {
            this.events[eventName].forEach(function(fn) {
                fn(data);
            });
        }
    }
}

export default new Event();

index.js

 import Vue from 'vue';
import $bus from '.../event.js';

const app = Vue.createApp({})
app.config.globalProperties.$bus = $bus;

原文由 magistr4815 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题