跳至内容

事件 API
中断

概述

$on$off$once 实例方法已移除。组件实例不再实现事件发射器接口。

2.x 语法

在 2.x 中,Vue 实例可用于触发通过事件发射器 API($on$off$once)强制附加的处理程序。这可用于创建事件总线,以创建用于整个应用程序的全局事件侦听器

js
// eventBus.js

const eventBus = new Vue()

export default eventBus
js
// ChildComponent.vue
import eventBus from './eventBus'

export default {
  mounted() {
    // adding eventBus listener
    eventBus.$on('custom-event', () => {
      console.log('Custom event triggered!')
    })
  },
  beforeDestroy() {
    // removing eventBus listener
    eventBus.$off('custom-event')
  }
}
js
// ParentComponent.vue
import eventBus from './eventBus'

export default {
  methods: {
    callGlobalCustomEvent() {
      eventBus.$emit('custom-event') // if ChildComponent is mounted, we will have a message in the console
    }
  }
}

3.x 更新

我们从实例中完全移除了 $on$off$once 方法。$emit 仍然是现有 API 的一部分,因为它用于触发由父组件声明式附加的事件处理程序。

迁移策略

迁移构建标志:INSTANCE_EVENT_EMITTER

在 Vue 3 中,不再可以使用这些 API 从组件内部侦听组件自身发出的事件。此用例没有迁移路径。

根组件事件

可以通过将静态事件侦听器作为道具传递给 createApp 来将其添加到根组件。

js
createApp(App, {
  // Listen for the 'expand' event
  onExpand() {
    console.log('expand')
  }
})

事件总线

事件总线模式可以使用实现事件发射器接口的外部库来替换,例如 mitttiny-emitter

示例

js
// eventBus.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)
}

这提供了与 Vue 2 中相同的事件发射器 API。

在大多数情况下,不建议使用全局事件总线在组件之间进行通信。虽然它通常是短期内最简单的解决方案,但它几乎总是会在长期内证明是维护上的麻烦。根据具体情况,使用事件总线有各种替代方案

  • 道具和事件应该是你进行父子通信的首选。兄弟姐妹可以通过其父级进行通信。
  • Provide / inject 允许组件与其插槽内容进行通信。这对于始终一起使用的紧密耦合组件很有用。
  • Provide / inject 也可用于组件之间的长距离通信。它有助于避免“道具钻取”,即道具需要通过许多不需要这些道具本身的组件级别传递。
  • 道具钻取也可以通过重构为使用插槽来避免。如果中间组件不需要道具,那么它可能表明存在关注点分离问题。在该组件中引入插槽允许父级直接创建内容,以便可以传递道具而无需中间组件参与。
  • 全局状态管理,例如 Pinia