Vue3 组件通信了解吗?

292 阅读1分钟

colorful-meadow-flowers-under-the-mountains-free-photo.webp

Vue 3 引入了 Composition API,提供了更多灵活的组件通信方式,以下是一些 Vue 3 中组件通信的代码示例:

1. Props 和 Emits

父组件向子组件传递数据使用 props,子组件通过 $emit 向父组件发送事件。

父组件:

<template>
  <ChildComponent :parentMessage="message" @childEvent="handleChildEvent" />
</template>

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

const message = ref('Hello from parent!');

function handleChildEvent(data) {
  console.log('Message from child:', data);
}
</script>

子组件:

<template>
  <div @click="emitMessage">
    {{ parentMessage }}
  </div>
</template>

<script setup>
import { defineProps, defineEmits } from 'vue';

const props = defineProps({
  parentMessage: String
});

const emit = defineEmits(['childEvent']);

function emitMessage() {
  emit('childEvent', 'Hello from child!');
}
</script>

2. v-model

在 Vue 3 中,v-model 用于创建父子组件之间的双向绑定。

父组件:

<template>
  <ChildComponent v-model:title="pageTitle" />
</template>

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

const pageTitle = ref('Initial Title');
</script>

子组件:

<template>
  <input type="text" :value="title" @input="updateTitle" />
</template>

<script setup>
import { defineProps, defineEmits } from 'vue';

const props = defineProps({
  title: String
});

const emit = defineEmits(['update:title']);

function updateTitle(event) {
  emit('update:title', event.target.value);
}
</script>

3. provide / inject

允许祖先组件向所有子孙后代组件提供数据,不论层次结构有多深。

祖先组件:

<template>
  <div>
    <ChildComponent />
  </div>
</template>

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

const theme = ref('dark');

provide('theme', theme);
</script>

子孙组件:

<template>
  <div>
    The theme is: {{ theme }}
  </div>
</template>

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

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

4. Event Bus (使用第三方库如 mitt)

虽然 Vue 3 官方不推荐使用 EventBus,但可以通过第三方库如 mitt 实现。

创建 event bus:

// eventBus.js
import mitt from 'mitt';
const eventBus = mitt();
export default eventBus;

在组件中使用:

<template>
  <button @click="emitEvent">Emit Event</button>
</template>

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

function emitEvent() {
  eventBus.emit('custom-event', 'Hello World!');
}
</script>

5. Refs 和 defineExpose

父组件可以通过 ref 获取子组件实例,并使用 defineExpose 在子组件中暴露数据或方法。

父组件:

<template>
  <ChildComponent ref="child" />
</template>

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

const child = ref(null);

// 假设子组件暴露了 `exposedMethod`
child.value.exposedMethod();
</script>

子组件:

<script setup>
import { defineExpose, ref } from 'vue';

const exposedData = ref('Some data');
const exposedMethod = () => {
  console.log('Exposed method called');
};

defineExpose({
  exposedData,
  exposedMethod
});
</script>