兄弟组件传参
- 子组件A通过defineEmits给父组件派发一个事件,并传递一个参数flag,代码如下:
vue
<template>
<div>
<button @click="emitB">派发一个事件</button>
</div>
</template>
<script setup lang='ts'>
import { ref } from 'vue'
const emit = defineEmits(['on-click'])
let flag = false
const emitB = () => {
flag = !flag
emit('on-click', flag)
}
</script>
<style scoped></style>
- 父组件通过注册on-click事件来接收到子组件A传过来的值flag
- 父组件通过v-bind向子组件B传递参数Flag
vue
<template>
<div>
<A @on-click="getFlag"></A>
<B :flag="Flag"></B>
</div>
</template>
<script setup lang='ts'>
import { ref } from 'vue'
import A from './A.vue'
import B from './B.vue'
let Flag = ref(false)
const getFlag = (flag: boolean) => {
Flag.value = flag
}
</script>
<style scoped></style>
- 子组件B通过defineProps接收父组件传过来的值flag
vue
<template>
<div>
{{ flag }}
</div>
</template>
<script setup lang='ts'>
import { ref } from 'vue'
type Props = {
flag: boolean
}
defineProps<Props>()
</script>
<style scoped></style>
这样当子组件A进行派发事件修改flag的值,其兄弟组件B中的flag也会改变。也就完成了兄弟组件传参。
发布-订阅模式
发布-订阅模式(Pub-Sub pattern)的事件总线(Event Bus)。它创建了一个消息系统,允许多个对象(称为订阅者)监听某个事件(称为主题),当这个事件被触发(发布)时,所有订阅了这个事件的对象都会收到通知。
代码如下:
typescript
// 发布-订阅模式
type BusClass<T> = {
emit: (name: T) => void
on: (name: T, callback: Function) => void
off: (name: T, callback: Function) => void
once: (name: T, callback: Function) => void
}
type PramsKey = string | number | symbol
type List = {
[key: PramsKey]: Array<Function>
}
class Bus<T extends PramsKey> implements BusClass<T> {
list: List
constructor() {
this.list = {}
}
// 调用所有订阅了这个事件的回调函数,并传入参数
emit(name: T, ...args: Array<any>) {
let eventName: Array<Function> = this.list[name] || []
eventName.forEach(fn => {
fn.apply(this, args)
})
}
// 将回调函数添加到这个事件的订阅者列表中
on(name: T, callback: Function) {
let fn: Array<Function> = this.list[name] || []
fn.push(callback)
this.list[name] = fn
}
// 从这个事件的订阅者列表中移除这个回调函数
off(name: T, callback: Function) {
let fn: Array<Function> = this.list[name] || []
this.list[name] = fn.filter(f => {
f !== callback
})
}
// wrappedCallback会在被触发时调用原始的回调函数,并使用 off 方法取消订阅这个事件
once(name: T, callback: Function) {
const wrappedCallback = (...args: Array<any>) => {
callback.apply(this, args)
this.off(name, wrappedCallback)
}
this.on(name, wrappedCallback)
}
}
export default new Bus<string>()
这时候,父组件只需要引入A和B两个子组件,B组件通过调用Bus类的on
方法注册回调函数:
vue
<script setup lang='ts'>
import { ref } from 'vue'
import bus from '../../utils/Bus.ts'
let flag = ref(false)
bus.on('on-click',(Flag:boolean)=>{
flag.value=Flag
})
</script>
A组件通过调用Bus类的emit
方法调用相应的回调函数:
vue
<script setup lang='ts'>
import { ref } from 'vue'
import bus from '../../utils/Bus.ts'
const emit = defineEmits(['on-click'])
let flag = false
const emitB = () => {
flag = !flag
bus.emit('on-click', flag)
}
</script>
这种方式不需要通过父组件即可完成兄弟组件传参。