vue3实现组件通信

在 Vue 3 中,组合式 API(Composition API)是一个重要的新特性,用于更灵活和高效地组织组件逻辑。下面我们将介绍如何在 Vue 3 中使用组合式 API 实现组件通信。

1. 父子组件通信

1.1 父 -> 子通信:props

父组件通过 props 传递数据给子组件,子组件通过 defineProps 函数接收这些数据。

示例:
<!-- 父组件 Parent.vue -->
<template>
  <ChildComponent :message="parentMessage" />
</template>

<script setup>
import ChildComponent from './ChildComponent.vue';

const parentMessage = 'Hello from Parent!';
</script>

<!-- 子组件 ChildComponent.vue -->
<template>
  <p>{{ message }}</p>
</template>

<script setup>
const props = defineProps({
  message: String
});
</script>

在这个例子中,父组件通过 props 向子组件传递了 parentMessage,子组件通过 defineProps 获取这个数据。

1.2 子 -> 父通信:emit

子组件可以通过 emit 触发事件,父组件通过监听这个事件获取子组件传递的数据。

示例:
<!-- 父组件 Parent.vue -->
<template>
  <ChildComponent @customEvent="handleEvent" />
</template>

<script setup>
import ChildComponent from './ChildComponent.vue';

function handleEvent(payload) {
  console.log('Received from child:', payload);
}
</script>

<!-- 子组件 ChildComponent.vue -->
<template>
  <button @click="sendMessage">Send Message to Parent</button>
</template>

<script setup>
const emit = defineEmits(['customEvent']);

function sendMessage() {
  emit('customEvent', 'Hello from Child!');
}
</script>

子组件通过 emit 触发了一个自定义事件 customEvent,父组件监听这个事件并获取传递的消息。

2. 非父子组件通信

2.1 事件总线(Event Bus)

在 Vue 3 中,由于不能直接使用 Vue 实例作为事件总线,推荐使用 mitt 这个轻量的事件库。

安装 mitt
npm install mitt
使用 mitt 实现事件总线通信:
// eventBus.js
import mitt from 'mitt';

export const eventBus = mitt();
示例:
<!-- 组件A ComponentA.vue (发送消息) -->
<template>
  <button @click="sendMessage">Send Message to Component B</button>
</template>

<script setup>
import { eventBus } from './eventBus.js';

function sendMessage() {
  eventBus.emit('message', 'Hello from Component A!');
}
</script>

<!-- 组件B ComponentB.vue (接收消息) -->
<template>
  <p>{{ message }}</p>
</template>

<script setup>
import { eventBus } from './eventBus.js';
import { ref, onMounted, onUnmounted } from 'vue';

const message = ref('');

onMounted(() => {
  eventBus.on('message', (msg) => {
    message.value = msg;
  });
});

onUnmounted(() => {
  eventBus.off('message');
});
</script>

组件 A 通过 eventBus.emit 发送消息,组件 B 通过 eventBus.on 接收消息。mitt 提供了简洁的 API 来实现事件的发送与接收。

2.2 使用 Vuex (或 Pinia) 进行全局状态管理

在 Vue 3 中,推荐使用 Pinia 作为状态管理库,取代 Vuex,因为它更加现代和轻量。

安装 Pinia:
npm install pinia
创建 Pinia Store:
// store.js
import { defineStore } from 'pinia';

export const useMainStore = defineStore('main', {
  state: () => ({
    message: ''
  }),
  actions: {
    updateMessage(newMessage) {
      this.message = newMessage;
    }
  }
});
使用 Store:
<!-- 组件A ComponentA.vue (发送消息) -->
<template>
  <button @click="sendMessage">Send Message to Store</button>
</template>

<script setup>
import { useMainStore } from './store.js';

const store = useMainStore();

function sendMessage() {
  store.updateMessage('Hello from Component A!');
}
</script>

<!-- 组件B ComponentB.vue (接收消息) -->
<template>
  <p>{{ store.message }}</p>
</template>

<script setup>
import { useMainStore } from './store.js';

const store = useMainStore();
</script>

组件 A 通过 store.updateMessage 更新全局状态,组件 B 通过 store.message 响应式地获取全局状态。

3. 跨级组件通信:provideinject

在 Vue 3 中,provideinject 也是通过组合式 API 来实现的,可以用于父级组件向任意深度的子组件提供数据。

示例:
<!-- 父组件 Parent.vue -->
<template>
  <ChildComponent />
</template>

<script setup>
import { provide } from 'vue';

const message = 'Hello from Parent';
provide('sharedMessage', message);
</script>

<!-- 子组件 ChildComponent.vue -->
<template>
  <p>{{ sharedMessage }}</p>
</template>

<script setup>
import { inject } from 'vue';

const sharedMessage = inject('sharedMessage');
</script>

父组件通过 provide 提供数据,任意深度的子组件通过 inject 获取该数据。

4. 使用 ref 访问子组件实例

父组件可以通过 ref 来直接访问子组件实例中的方法和属性。

示例:
<!-- 父组件 Parent.vue -->
<template>
  <ChildComponent ref="childRef" />
  <button @click="callChildMethod">Call Child Method</button>
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const childRef = ref(null);

function callChildMethod() {
  childRef.value.someMethod();
}
</script>

<!-- 子组件 ChildComponent.vue -->
<template>
  <p>Child Component</p>
</template>

<script setup>
function someMethod() {
  console.log('Child method called!');
}
</script>

父组件通过 ref 获取子组件实例,然后调用子组件中的方法。

5. 透传 attrslisteners

在 Vue 3 中,attrslisteners 的使用被简化,可以通过 useAttrs 来访问所有未声明的 props,并通过 v-bind 进行透传。

示例:
<!-- 父组件 Parent.vue -->
<template>
  <ChildComponent :message="parentMessage" @customEvent="handleEvent" />
</template>

<script setup>
const parentMessage = 'Hello from Parent!';
function handleEvent(data) {
  console.log('Received event:', data);
}
</script>

<!-- 子组件 ChildComponent.vue -->
<template>
  <GrandChildComponent v-bind="$attrs" />
</template>

<script setup>
import { useAttrs } from 'vue';

const attrs = useAttrs();
</script>

<!-- 孙组件 GrandChildComponent.vue -->
<template>
  <p>{{ message }}</p>
  <button @click="$emit('customEvent', 'Hello from GrandChild')">Emit Event</button>
</template>

<script setup>
const props = defineProps({
  message: String
});
</script>

父组件的 props 和事件通过 $attrs 传递到孙组件,孙组件通过 $emit 触发事件。

总结

在 Vue 3 中使用组合式 API 可以更加灵活地实现组件通信,具体方式包括:

  1. 父 -> 子通信:通过 propsdefineProps
  2. 子 -> 父通信:通过 $emitdefineEmits
  3. 跨组件通信:通过事件总线(如 mitt)或 Pinia(状态管理)。
  4. 跨级组件通信:使用 provideinject
  5. 访问子组件实例:通过 ref
  6. 透传 attrslisteners

这些方法在组合式 API 的支持下变得更加简洁高效,非常适合在 Vue 3 中使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值