组件通信的九种方式🤔

引言💭

在 Vue3 开发中,组件化是构建前端应用的重要方式,而组件之间的数据通信则是必不可少的环节。不同的业务场景需要采用不同的通信方式,下面就来看看常见的九种组件通信方式。

1. props 传递数据(父组件 -> 子组件)

props 是 Vue 组件间通信最常见的方式,主要用于父组件向子组件传递数据。子组件使用 defineProps() 来接收数据。

适用场景

适用于父组件需要向子组件传递静态或动态数据的情况。

示例代码

xml 复制代码
// 父组件
<template>
  <Child :message="parentMessage" />
</template>
<script setup>
import Child from './Child.vue';
import { ref } from 'vue';
const parentMessage = ref('来自父组件的消息');
</script>
xml 复制代码
// 子组件
<script setup>
import { defineProps } from 'vue';
const props = defineProps(['message']);
</script>
<template>
  <p>{{ props.message }}</p>
</template>

2. 自定义事件(子组件 -> 父组件)

当子组件需要向父组件传递数据时,可以使用 defineEmits() 定义并触发事件。

适用场景

适用于子组件向父组件反馈信息,例如表单提交、按钮点击等。

示例代码

xml 复制代码
// 父组件
<template>
  <Child @update-message="handleUpdate" />
</template>
<script setup>
import Child from './Child.vue';
import { ref } from 'vue';
const message = ref('初始消息');
function handleUpdate(newMessage) {
  message.value = newMessage;
}
</script>
xml 复制代码
// 子组件
<script setup>
import { defineEmits } from 'vue';
const emit = defineEmits(['update-message']);
function sendMessage() {
  emit('update-message', '新的消息');
}
</script>
<template>
  <button @click="sendMessage">发送消息</button>
</template>

3. mitt (全局事件总线)

mitt 允许任意组件之间进行通信,无需父子关系。

适用场景

适用于兄弟组件或非直接关系组件之间的通信。

示例代码

javascript 复制代码
// eventBus.js
import mitt from 'mitt';
export const emitter = mitt();
xml 复制代码
// 组件A(发送事件)
<script setup>
import { emitter } from './eventBus';
function sendEvent() {
  emitter.emit('custom-event', '跨组件数据');
}
</script>
<template>
  <button @click="sendEvent">发送事件</button>
</template>
xml 复制代码
// 组件B(监听事件)
<script setup>
import { emitter } from './eventBus';
import { onMounted } from 'vue';
onMounted(() => {
  emitter.on('custom-event', (data) => {
    console.log('接收到数据:', data);
  });
});
</script>
<template>
  <p>监听事件</p>
</template>

4. v-model (双向绑定父子组件通信)

用于父组件与子组件之间的双向数据绑定。

适用场景

适用于表单组件,如输入框、选择框等。

示例代码

ini 复制代码
// 父组件
<Child v-model="parentValue" />
xml 复制代码
// 子组件
<script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps(['modelValue']);
const emit = defineEmits(['update:modelValue']);
</script>
<template>
  <input :value="props.modelValue" @input="emit('update:modelValue', $event.target.value)" />
</template>

5. $attrs 进行祖孙组件通信

用于祖组件传递 props 给孙组件,而不需要父组件声明 props

适用场景

适用于多层组件嵌套时,避免中间层组件重复声明 props

示例代码

ini 复制代码
// 祖组件
<Parent msg="Hello" />
ini 复制代码
// 父组件
<Child v-bind="$attrs" />
xml 复制代码
// 孙组件
<script setup>
import { useAttrs } from 'vue';
const attrs = useAttrs();
</script>
<template>
  <p>{{ attrs.msg }}</p>
</template>

6. refs 和 parent

  • $refs 获取子组件实例。
  • $parent 获取父组件实例。

适用场景

适用于需要直接操作组件实例的情况。

示例代码

javascript 复制代码
// 父组件
<Child ref="childRef" />
<script setup>
import { ref, onMounted } from 'vue';
const childRef = ref(null);
onMounted(() => {
  console.log(childRef.value);
});
</script>

7. provide-inject (祖孙组件通信)

适用场景

适用于祖孙组件共享数据,无需父组件中转。

示例代码

xml 复制代码
// 祖组件
<script setup>
import { provide } from 'vue';
provide('message', '来自祖组件的数据');
</script>
xml 复制代码
// 孙组件
<script setup>
import { inject } from 'vue';
const message = inject('message');
</script>
<template>
  <p>{{ message }}</p>
</template>

8. Pinia (状态管理工具)

Pinia 允许多个组件共享状态。

适用场景

适用于应用全局状态管理。

示例代码

javascript 复制代码
import { defineStore } from 'pinia';
export const useStore = defineStore('main', {
  state: () => ({ message: '共享数据' }),
});
xml 复制代码
<script setup>
import { useStore } from './store';
const store = useStore();
</script>
<template>
  <p>{{ store.message }}</p>
</template>

9. slot (插槽)

插槽用于在组件内部指定可插入的内容。

示例代码

xml 复制代码
<template>
  <slot>默认内容</slot>
</template>

具名插槽:

xml 复制代码
<template>
  <slot name="header"></slot>
  <slot></slot>
  <slot name="footer"></slot>
</template>

结语✍🏻

记住了这九种组件通信方式,我们在面试中就能侃侃而谈。😁

相关推荐
爱勇宝1 小时前
鸿蒙生态的下半场:开发者不只要能开发,还要能赚钱
android·前端·程序员
IT_陈寒4 小时前
SpringBoot这个自动配置坑我跳了三次
前端·人工智能·后端
kyriewen4 小时前
我用 AI 一周写完了整个项目,上线第一天就崩了——这是我踩过最贵的 5 个坑
前端·javascript·ai编程
牧艺5 小时前
从零到协同:构建类飞书在线文档系统的五个技术重难点
前端·人工智能
红尘散仙6 小时前
想写一个像样的终端 App?试试把 React 的开发体验搬进 Rust TUI
前端·rust
袋鼠云数栈UED团队6 小时前
一套 Spec-First 的 AI 编程工作流
前端·人工智能
袋鼠云数栈前端6 小时前
一套 Spec-First 的 AI 编程工作流
前端·ai+
angerdream7 小时前
Android手把手编写儿童手机远程监控App之vue3 路由守卫
前端
不服老的小黑哥7 小时前
AI规范驱动编程-harness工程项目实战
前端
vivo互联网技术7 小时前
从 Web 到桌面:基于 Tauri 2.0 + Vue 3 打造 vivo 线下门店「大头贴」拍照体验系统
前端·rust