如何在 Vue 3 上创建本地事件总线

Gor*_*lka 9 vue.js vuejs3

如何在一个页面上使用事件总线,以便所有组件和页面都可以读取和接收那里的事件例如,在 vue 2 中,我创建了一个对象,该对象在创建页面时分配了上下文的字段,并且我使用了页面所有组件中的此上下文示例

//main.js
global.context = new Object();
global.context.app = Vue;

//field assignment with context
global.context.authorization = this;
 
//using context
global.context.authorization.$emit(
  "authorizationMessage",
  this.t("Password fields didn't match")
);
Run Code Online (Sandbox Code Playgroud)

我可以使用导入来改进这种方法吗?在 vue 3 中,我使用时遇到错误

global.context.authorization.$on("authorizationMessage", (msg) => {
  alert(msg);
});
Run Code Online (Sandbox Code Playgroud)
Uncaught (in promise) TypeError: global.context.authorization.$on is not a function
    at Proxy.created (Messenger.vue?1b1a:25)
    at callWithErrorHandling (runtime-core.esm-bundler.js?5c40:154)
    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js?5c40:163)
    at callHookWithMixinAndExtends (runtime-core.esm-bundler.js?5c40:6032)
    at callSyncHook (runtime-core.esm-bundler.js?5c40:6018)
    at applyOptions (runtime-core.esm-bundler.js?5c40:5956)
    at finishComponentSetup (runtime-core.esm-bundler.js?5c40:6636)
    at setupStatefulComponent (runtime-core.esm-bundler.js?5c40:6567)
    at setupComponent (runtime-core.esm-bundler.js?5c40:6503)
    at mountComponent (runtime-core.esm-bundler.js?5c40:4206)
Run Code Online (Sandbox Code Playgroud)

Ndi*_*asi 12

  1. Vue 3 中没有事件总线。所以$on不起作用。请参阅:https ://v3-migration.vuejs.org/writing-changes/events-api.html#events-api

  2. 建议您使用外部库创建事件总线,除非您想利用受支持的父子基于事件的通信,其中子级发出只能由父级监听的事件。请参阅:https://v3.vuejs.org/guide/component-custom-events.html#custom-events

  3. 要为您的应用程序实现事件总线,请确保您正在发出(激发)事件并使用同一发射器实例侦听它们。不然就不行了

  4. 我更喜欢emitteryhttps://github.com/sindresorhus/emittery)使用 Vue js 的事件总线。它非常强大,具有出色的 Typescript 支持。我还通过 Adonisjs 框架在 Node js 上使用它。

  5. 创建一个 useEvent 挂钩 //文件:composables/useEvent.ts

import Emittery from 'emittery';
const emitter = new Emittery();
// Export the Emittery class and its instance.
// The `emitter` instance is more important for us here
export {emitter, Emittery};
Run Code Online (Sandbox Code Playgroud)

// 导出 Emittery 类及其实例 export {emitter, Emittery };

  1. 在任何 vue 组件中监听事件 // 文件:AnyVueComponent.vue
<script lang="ts">
import { defineComponent, onMounted } from 'vue';
import {emitter} from '../composables/useEvent'

export default defineComponent({
  name: 'ExampleComponent',
  components: {},
  props: {},
  setup() {
    onMounted(() => {
      emitter.on('event-name', async () => {
        // Perform actions. async...await is supported
      });
    })
    return {};
  },
});
</script>
Run Code Online (Sandbox Code Playgroud)
  1. 在任何 vue 组件中发出事件
<script lang="ts">
import { defineComponent, onMounted } from 'vue';
import {emitter} from '../composables/useEvent'

export default defineComponent({
  name: 'ExampleComponent',
  components: {},
  props: {},
  setup() {
    void emitter.emit('event-name');
    return {};
  },
});
</script>
Run Code Online (Sandbox Code Playgroud)
  1. 请注意,您可以将useEvent钩子导入到任何非 Vue 文件中,它就会起作用。它只是一个 JS/TS 文件。

对于 Quasar 框架:

  1. 创建启动文件
import Emittery from 'emittery';
const emitter = new Emittery();
// Export the Emittery class and its instance.
// The `emitter` instance is more important for us here
export {emitter, Emittery};
Run Code Online (Sandbox Code Playgroud)
  1. // 文件:EventBus.ts
import { boot } from 'quasar/wrappers';
import Emittery from 'emittery';

const emitter = new Emittery();

export default boot(({ app }) => {
  app.config.globalProperties.$event = emitter;
});

// Export the Emittery class and its instance
export { emitter, Emittery };
Run Code Online (Sandbox Code Playgroud)
  1. quasar.conf.js用文件注册
<script lang="ts">
import { defineComponent, onMounted } from 'vue';
import {emitter} from '../composables/useEvent'

export default defineComponent({
  name: 'ExampleComponent',
  components: {},
  props: {},
  setup() {
    onMounted(() => {
      emitter.on('event-name', async () => {
        // Perform actions. async...await is supported
      });
    })
    return {};
  },
});
</script>
Run Code Online (Sandbox Code Playgroud)
  1. 在任何 vue 组件中监听事件 // 文件:AnyVueComponent.vue
<script lang="ts">
import { defineComponent, onMounted } from 'vue';
import {emitter} from '../boot/EventBus'

export default defineComponent({
  name: 'ExampleComponent',
  components: {},
  props: {},
  setup() {
    onMounted(() => {
      emitter.on('event-name', async () => {
        // Perform actions. async...await is supported
      });
    })
    return {};
  },
});
</script>
Run Code Online (Sandbox Code Playgroud)
  1. 在任何 vue 组件中发出事件
<script lang="ts">
import { defineComponent, onMounted } from 'vue';
import {emitter} from '../boot/EventBus'

export default defineComponent({
  name: 'ExampleComponent',
  components: {},
  props: {},
  setup() {
    void emitter.emit('event-name');
    return {};
  },
});
</script>
Run Code Online (Sandbox Code Playgroud)


ton*_*y19 5

按照用作Vue事件总线的Vue 3 迁移指南,将该总线替换为以下实例tiny-emitter

// event-bus.js
import emitter from 'tiny-emitter/instance'

export default {
  $on: (...args) => emitter.on(...args),
  $once: (...args) => emitter.once(...args),
  $off: (...args) => emitter.off(...args),
  $emit: (...args) => emitter.emit(...args),
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

// main.js
import eventBus from './event-bus'

//...
global.context.authorization = eventBus
Run Code Online (Sandbox Code Playgroud)

演示