vue-broadcaster
Version:
236 lines (166 loc) • 6.77 kB
Markdown
# vue-broadcaster [![NPM Version][npm-version-image]][npm-url] [![NPM Downloads][npm-downloads-image]][npm-url]
基于 Vue3 `provide/inject` 的广播组合式 API。
中文 | [English](https://github.com/xiangheng08/vue-broadcaster/blob/HEAD/README.en.md)
## 特点
- 体积小巧,除 Vue3 不依赖任何第三方库,构建产物 < 4KB
- 简单易用,无需复杂配置,即装即用
- 可自定义 [`InjectionKey`](https://vuejs.org/api/composition-api-dependency-injection.html)
## 安装
```bash
npm i vue-broadcaster
```
## 什么是 vue-broadcaster?
假设有如下组件结构:
```
Parent.vue
├── Child1.vue
└── Child2.vue
├── Child2-1.vue
└── Child2-2.vue
```
假设 `Child1.vue` 和 `Child2.vue` 的数据需要请求不同的 API,而在 `Parent.vue` 中,需要在一些操作后通知 `Child1.vue` 和 `Child2.vue` 刷新数据。使用 `vue-broadcaster` 是这样的:
在 `Parent.vue` 中定义广播器:
```ts
import { useBroadcast } from 'vue-broadcaster'
const { broadcast } = useBroadcast()
const handleClick = () => {
// 发出刷新广播
broadcast('refresh')
}
```
在 `Child1.vue` 和 `Child2.vue` 中监听刷新广播:
```ts
import { useReceiveBroadcast } from 'vue-broadcaster'
useReceiveBroadcast('refresh', (data) => {
// 刷新数据
console.log('刷新数据')
})
```
这是一个基本的例子,实际应用中只要涉及类似的场景,都可以使用 `vue-broadcaster`。
## 什么是广播域?
我们知道 Vue 的 `provide` 提供数据后,在子组件和后代组件中都可以使用 `inject` 获取数据。`vue-broadcaster` 正是利用这一特点,再配合一个事件触发器,实现跨组件的广播。
还是上面那个组件结构:
```
Parent.vue
├── Child1.vue
└── Child2.vue
├── Child2-1.vue
└── Child2-2.vue
```
在 `Parent.vue` 中通过 `useBroadcast` 创建广播器,再使用 `provide` 提供给子组件和后代组件,那么 `Parent.vue` 及其子组件和后代组件就组成了一个广播域。
在整个广播域中,你可以在任意组件中发出广播,通知域中所有的组件。
> [!WARNING]
> 一个广播域中不能有两个及以上 [`InjectionKey`](https://vuejs.org/api/composition-api-dependency-injection.html) 是一样广播器,不然可能会冲突。
## API
### `useBroadcast`、`useReceiveBroadcast`、`useChildBroadcast`
这三个组合式 API 是一组的,需要搭配使用。
- `useBroadcast`:创建一个广播器,可以发出广播,也可以接收广播。_注意:只能域的根组件中使用。_
- `useReceiveBroadcast`:接收广播。_注意:只能域的在子组件和后代组件中使用。_
- `useChildBroadcast`:接收域中根组件的广播器,并返回一个广播发出器。_注意:只能域的在子组件和后代组件中使用。_
根组件:
```ts
import { useBroadcast } from 'vue-broadcaster'
const { broadcast, receive } = useBroadcast()
// 发出广播
broadcast('hello')
// 携带数据
broadcast('hello', { name: 'world' })
// 接收广播
const off = receive('hello', (data) => {
console.log(data)
// 可调用 off 停止接收广播
off()
})
// 只接收一次
receive('hello', (data) => {}, { once: true })
// 排除当前组件实例发出的广播
receive('hello', (data) => {}, { excludeSelf: true })
```
子组件和后代组件:
```ts
import { useReceiveBroadcast, useChildBroadcast } from 'vue-broadcaster'
// 接收广播
const off = useReceiveBroadcast('hello', (data) => {
console.log(data)
// 可调用 off 停止接收广播
off()
})
// 只接收一次
useReceiveBroadcast('hello', (data) => {}, { once: true })
// 排除当前组件实例发出的广播
useReceiveBroadcast('hello', (data) => {}, { excludeSelf: true })
const broadcast = useChildBroadcast()
// 发出广播
broadcast('hello')
// 携带数据
broadcast('hello', { name: 'world' })
```
### `useGlobalBroadcast`、`useGlobalReceiveBroadcast`、`useGlobalChildBroadcast`
这三个组合式 API 是前面三个组合式 API 的变种,只有使用的 [`InjectionKey`](https://vuejs.org/api/composition-api-dependency-injection.html) 与前面三个不一样,使用的方式是基本一样的,只是含义不同。
注意:`useGlobalBroadcast` 会稍有不同,推荐在 `App.vue` 中使用,这样才能确保所有组件都可以接收到广播。
`App.vue`:
```vue
<script setup>
import { useGlobalBroadcast } from 'vue-broadcaster'
const { broadcast, receive } = useGlobalBroadcast()
// 发出广播
broadcast('hello')
// 携带数据
broadcast('hello', { name: 'world' })
// 接收广播
const off = receive('hello', (data) => {
console.log(data)
// 可调用 off 停止接收广播
off()
})
// 只接收一次
receive('hello', (data) => {}, { once: true })
// 排除当前组件实例发出的广播
receive('hello', (data) => {}, { excludeSelf: true })
</script>
```
子组件和后代组件:
```ts
import { useGlobalReceiveBroadcast, useGlobalChildBroadcast } from 'vue-broadcaster'
// 接收广播
const off = useGlobalReceiveBroadcast('hello', (data) => {
console.log(data)
// 可调用 off 停止接收广播
off()
})
// 只接收一次
useGlobalReceiveBroadcast('hello', (data) => {}, { once: true })
// 排除当前组件实例发出的广播
useGlobalReceiveBroadcast('hello', (data) => {}, { excludeSelf: true })
const broadcast = useGlobalChildBroadcast()
// 发出广播
broadcast('hello')
// 携带数据
broadcast('hello', { name: 'world' })
```
### `createBroadcastCompositions`
使用这个函数的可以创建一组广播组合式 API。如果你担心 [`InjectionKey`](https://vuejs.org/api/composition-api-dependency-injection.html) 的冲突,你可以使用 `createBroadcastCompositions` 创建一组广播组合式 API。
`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
```
## 开发
```bash
git clone https://github.com/xiangheng08/vue-broadcaster.git
cd vue-broadcaster
pnpm i
pnpm dev # 启动开发服务
pnpm 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