使用 mitt 在 Nuxt3 中实现Event-bus

1,402 阅读1分钟

在父子组件传递数据和方法时,会使用 props 和 emits ,当有一些多层级嵌套的组件,某个深层的子组件需要一个较远的祖先组件中的部分数据,我们还可以使用依赖注入(provide/inject)的方式来实现,但当深层子组件需要触发事件来修改祖先组件的数据时,逐级透传就会变的非常麻烦, 使用 Event-bus 进行组件通信帮我们解决了这一问题:

Vue3.x 不再提供 Vue2.x 里的 $on$emit这两个实例方法,Vue3.x 中更推荐使用 mitt 这个库来实现

在 Nuxt3 中使用 mitt

1,以 plugins 的方式使用mitt

假设你已经了解 Nuxt 插件的工作方式 更多请查阅: nuxt.com/docs/guide/…

安装 mitt

npm install --save mitt

更多请查阅 mitt 文档

在根目录下创建plugins/event-bus.ts

// plugins/event-bus.ts
import mitt from 'mitt'

// 为 mitt 方法里的’modify-user‘事件标注类型
interface ModifyUser {
  id: number
  name: string
}

// 为 mitt 方法标注类型
type ApplicationEvents = {
  'delete-user': number
  'modify-user': ModifyUser
}

export default defineNuxtPlugin(() => {

  const emitter = mitt<ApplicationEvents>()

  return {
    provide: {
      emits: emitter.emit, // 触发事件方法 $emits
      on: emitter.on // 监听事件方法 $on
    }
  }
})

在组件中使用

父组件:

// App.vue
<script setup lang="ts">
// 监听事件
const { $on } = useNuxtApp()
$on('delete-user', (id) => {
  userList.value.forEach((item, index) => {
    if (item.id === id) {
      userList.value.splice(index, 1)
    }
  })
})
$on('modify-user', (userInfo) => {
  const { id, name } = userInfo
  userList.value.forEach((item) => {
    if (item.id === id) {
      item.name = name
    }
  })
})
</script>

后代组件:

// GrandChild.vue
<script setup lang="ts">
const { $emits } = useNuxtApp()
// 触发事件
const deleteUser = (id) => {
  $emits('delete-user', id)
}

const modifyUser = (id,name) => {
  customData.value.title = (e.target as HTMLInputElement).value
  $emits('modify-title', {
    id: id,
    name: userName
  })
}
</script>

2,以 composables 的方式使用 mitt

在根目录下创建 composables/useEventBus.ts

// composables/useEventBus.ts
import mitt from 'mitt'

// 为 mitt 方法里的’modify-user‘事件标注类型
interface ModifyUser {
  id: number
  name: string
}

// 为 mitt 方法标注类型
type ApplicationEvents = {
  'delete-user': number
  'modify-user': ModifyUser
}

const emitter = mitt<ApplicationEvents>()

export const useEmit = emitter.emit, // 触发事件方法 $emits
export const useOn = emitter.on // 监听事件方法 $on
    }
  }
})

在组件中使用

得益于Nuxt的自动导入功能,我们可以直接在组件中使用:

// App.vue
// 监听事件
useOn('delete-user',(id)=>{
    console.log('delete user by id')
})
// GrandChild.vue
// 触发事件
useEmit('delete-user',id)