vue-broadcaster
Version:
239 lines (168 loc) • 7.3 kB
Markdown
# vue-broadcaster [![NPM Version][npm-version-image]][npm-url] [![NPM Downloads][npm-downloads-image]][npm-url]
A Vue3 `provide/inject` based broadcast Composition API.
English | [中文](https://github.com/xiangheng08/vue-broadcaster/blob/HEAD/README.md)
> [!TIP]
> Translated by [Lingma](https://lingma.aliyun.com/). If you find any errors, please [submit an issue](https://github.com/xiangheng08/vue-broadcaster/issues)
## Features
- Lightweight, no third-party dependencies except Vue3, build output < 4KB
- Easy to use, no complex configuration required, plug and play
- Customizable [`InjectionKey`](https://vuejs.org/api/composition-api-dependency-injection.html)
## Installation
```bash
npm i vue-broadcaster
```
## What is vue-broadcaster?
Suppose we have the following component structure:
```
Parent.vue
├── Child1.vue
└── Child2.vue
├── Child2-1.vue
└── Child2-2.vue
```
Suppose `Child1.vue` and `Child2.vue` need to request different APIs for their data, and in `Parent.vue`, after some operations, we need to notify `Child1.vue` and `Child2.vue` to refresh their data. Using `vue-broadcaster` looks like this:
Define broadcaster in `Parent.vue`:
```ts
import { useBroadcast } from 'vue-broadcaster'
const { broadcast } = useBroadcast()
const handleClick = () => {
// Emit refresh broadcast
broadcast('refresh')
}
```
Listen to refresh broadcast in `Child1.vue` and `Child2.vue`:
```ts
import { useReceiveBroadcast } from 'vue-broadcaster'
useReceiveBroadcast('refresh', (data) => {
// Refresh data
console.log('Refresh data')
})
```
This is a basic example. In real applications, `vue-broadcaster` can be used in any similar scenarios.
## What is a broadcast domain?
We know that after Vue's `provide` provides data, `inject` can be used to retrieve data in child and descendant components. `vue-broadcaster` utilizes this feature along with an event emitter to implement cross-component broadcasting.
Still using the same component structure:
```
Parent.vue
├── Child1.vue
└── Child2.vue
├── Child2-1.vue
└── Child2-2.vue
```
In `Parent.vue`, create a broadcaster using `useBroadcast`, then provide it to child and descendant components using `provide`. Then `Parent.vue` and its child and descendant components form a broadcast domain.
Within the entire broadcast domain, you can emit broadcasts from any component to notify all components in the domain.
> [!WARNING]
> A broadcast domain cannot have two or more broadcasters with the same [`InjectionKey`](https://vuejs.org/api/composition-api-dependency-injection.html), otherwise conflicts may occur.
## API
### `useBroadcast`, `useReceiveBroadcast`, `useChildBroadcast`
These three Composition APIs work as a group and need to be used together.
- `useBroadcast`: Creates a broadcaster that can emit and receive broadcasts. _Note: Can only be used in the root component of a domain._
- `useReceiveBroadcast`: Receives broadcasts. _Note: Can only be used in child and descendant components of a domain._
- `useChildBroadcast`: Receives the broadcaster from the root component of a domain and returns a broadcast emitter. _Note: Can only be used in child and descendant components of a domain._
Root component:
```ts
import { useBroadcast } from 'vue-broadcaster'
const { broadcast, receive } = useBroadcast()
// Emit broadcast
broadcast('hello')
// With data
broadcast('hello', { name: 'world' })
// Receive broadcast
const off = receive('hello', (data) => {
console.log(data)
// Call off to stop receiving broadcasts
off()
})
// Receive only once
receive('hello', (data) => {}, { once: true })
// Exclude broadcasts emitted by the current component instance
receive('hello', (data) => {}, { excludeSelf: true })
```
Child and descendant components:
```ts
import { useReceiveBroadcast, useChildBroadcast } from 'vue-broadcaster'
// Receive broadcast
const off = useReceiveBroadcast('hello', (data) => {
console.log(data)
// Call off to stop receiving broadcasts
off()
})
// Receive only once
useReceiveBroadcast('hello', (data) => {}, { once: true })
// Exclude broadcasts emitted by the current component instance
useReceiveBroadcast('hello', (data) => {}, { excludeSelf: true })
const broadcast = useChildBroadcast()
// Emit broadcast
broadcast('hello')
// With data
broadcast('hello', { name: 'world' })
```
### `useGlobalBroadcast`, `useGlobalReceiveBroadcast`, `useGlobalChildBroadcast`
These three Composition APIs are variants of the previous three, only differing in the [`InjectionKey`](https://vuejs.org/api/composition-api-dependency-injection.html) used. The usage is basically the same, but with different meanings.
Note: `useGlobalBroadcast` is slightly different and is recommended to be used in `App.vue` to ensure all components can receive broadcasts.
`App.vue`:
```vue
<script setup>
import { useGlobalBroadcast } from 'vue-broadcaster'
const { broadcast, receive } = useGlobalBroadcast()
// Emit broadcast
broadcast('hello')
// With data
broadcast('hello', { name: 'world' })
// Receive broadcast
const off = receive('hello', (data) => {
console.log(data)
// Call off to stop receiving broadcasts
off()
})
// Receive only once
receive('hello', (data) => {}, { once: true })
// Exclude broadcasts emitted by the current component instance
receive('hello', (data) => {}, { excludeSelf: true })
</script>
```
Child and descendant components:
```ts
import { useGlobalReceiveBroadcast, useGlobalChildBroadcast } from 'vue-broadcaster'
// Receive broadcast
const off = useGlobalReceiveBroadcast('hello', (data) => {
console.log(data)
// Call off to stop receiving broadcasts
off()
})
// Receive only once
useGlobalReceiveBroadcast('hello', (data) => {}, { once: true })
// Exclude broadcasts emitted by the current component instance
useGlobalReceiveBroadcast('hello', (data) => {}, { excludeSelf: true })
const broadcast = useGlobalChildBroadcast()
// Emit broadcast
broadcast('hello')
// With data
broadcast('hello', { name: 'world' })
```
### `createBroadcastCompositions`
Using this function, you can create a set of broadcast Composition APIs. If you're concerned about conflicts with [`InjectionKey`](https://vuejs.org/api/composition-api-dependency-injection.html), you can use `createBroadcastCompositions` to create a set of broadcast Composition APIs.
`custom-broadcaster.ts`:
```ts
import { createBroadcastCompositions } from 'vue-broadcaster'
const CUSTOM_INJECTION_KEY = Symbol('custom_broadcaster')
const { useBroadcast, useReceiveBroadcast, useChildBroadcast } = createBroadcastCompositions({
injectionKey: CUSTOM_INJECTION_KEY,
})
export const useCustomBroadcast = useBroadcast
export const useCustomReceiveBroadcast = useReceiveBroadcast
export const useCustomChildBroadcast = useChildBroadcast
```
## Development
```bash
git clone https://github.com/xiangheng08/vue-broadcaster.git
cd vue-broadcaster
pnpm i
pnpm dev # Start development server
pnpm build # Build
```
## License
[MIT](https://github.com/xiangheng08/vue-broadcaster/blob/HEAD/LICENSE)
[npm-url]: https://www.npmjs.com/package/vue-broadcaster
[npm-version-image]: https://badgen.net/npm/v/vue-broadcaster
[npm-downloads-image]: https://badgen.net/npm/dm/vue-broadcaster