VUE3组件间通信
父子组件:使用 Props/Emits
祖先-后代:使用 Provide/Inject(替代 Vue 2 的 event bus)
复杂应用状态:使用 Pinia(推荐替代 Vuex)
组件间解耦通信:使用 Event Bus(mitt)
1.使用refs获取子组件实例
1.组合式api
父组件
<!-- 父组件 Parent.vue -->
<template>
<div>
<Child ref="childRef" />
<button @click="callChildMethod">调用子组件方法</button>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import Child from './Child.vue'
// 1. 创建 ref 引用
const childRef = ref(null)
// 2. 访问子组件实例
const callChildMethod = () => {
if (childRef.value) {
childRef.value.increment()
console.log('子组件 count:', childRef.value.count)
}
}
</script>
子组件
<!-- 子组件 Child.vue -->
<template>
<div>子组件</div>
</template>
<script setup>
import { ref } from 'vue'
// 子组件的内部数据和方法
const count = ref(0)
// 子组件的方法
const increment = () => {
count.value++
}
// 暴露给父组件访问的属性和方法
defineExpose({
count,
increment
})
</script>
2.选项式api
和vue2一样的使用this.$refs
2.使用provide、inject进行祖先、后代通信
<!-- 祖先组件 Ancestor.vue -->
<template>
<div>
<h2>祖先组件</h2>
<Parent />
</div>
</template>
<script setup>
import { provide, ref, reactive } from 'vue'
import Parent from './Parent.vue'
// 1. 提供普通值
const title = ref('应用标题')
provide('appTitle', title)
// 2. 提供响应式对象
const user = reactive({
name: '张三',
age: 25
})
provide('user', user)
// 3. 提供方法
const updateUser = (newData) => {
Object.assign(user, newData)
}
provide('updateUser', updateUser)
</script>
<!-- 后代组件 Descendant.vue -->
<template>
<div>
<h3>后代组件</h3>
<p>标题: {{ appTitle }}</p>
<p>用户名: {{ user.name }}</p>
</div>
</template>
<script setup>
import { inject } from 'vue'
// 1. 注入值(没有默认值)
const appTitle = inject('appTitle')
// 2. 注入响应式对象
const user = inject('user')
// 3. 注入方法
const updateUser = inject('updateUser')
// 4. 注入 Symbol key 的值
const theme = inject(ThemeSymbol)
// 5. 注入时提供默认值
const notExists = inject('notExists', '默认值')
</script>
3.v-model进行父子组件通信
<!-- 子组件 MyComponent.vue -->
<template>
<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)">
</template>
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
<!-- 父组件使用 -->
<MyComponent v-model="message" />
4.使用事件总线EventBus
// eventBus.js
import mitt from 'mitt'
// 创建事件总线实例
const emitter = mitt()
// 可创建多个不同用途的事件总线
export const globalEmitter = mitt()
export const userEmitter = mitt()
// 默认导出
export default emitter
使用
<!-- 组件 A(发送事件) -->
<template>
<button @click="sendMessage">发送消息</button>
</template>
<script setup>
import { useEventBus } from './eventBus'
// 发送事件
const sendMessage = () => {
// 发送简单数据
useEventBus.emit('message', 'Hello World')
// 发送复杂数据
useEventBus.emit('user-updated', {
id: 1,
name: '张三',
timestamp: new Date()
})
// 发送没有数据的事件
useEventBus.emit('refresh')
}
</script>
<!-- 组件 B(接收事件) -->
<template>
<div>收到消息: {{ message }}</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { useEventBus } from './eventBus'
const message = ref('')
// 事件处理函数
const handleMessage = (msg) => {
console.log('收到消息:', msg)
message.value = msg
}
const handleUserUpdate = (user) => {
console.log('用户更新:', user)
}
// 组件挂载时监听事件
onMounted(() => {
useEventBus.on('message', handleMessage)
useEventBus.on('user-updated', handleUserUpdate)
useEventBus.on('refresh', () => {
console.log('刷新事件触发')
})
// 监听所有事件
useEventBus.on('*', (type, event) => {
console.log('所有事件监听:', type, event)
})
})
// 组件卸载时移除监听
onUnmounted(() => {
useEventBus.off('message', handleMessage)
useEventBus.off('user-updated', handleUserUpdate)
// 移除所有监听器
// useEventBus.all.clear()
})
</script>
由于无法解释的神圣旨意,我们徒然地到处找你;你就是孤独,你就是神秘,比恒河或者日落还要遥远。。。。。。

浙公网安备 33010602011771号