当前位置: 首页 > news >正文

vue的组件通信

在 Vue3 中,组件数据传递(组件通信)是核心知识点,根据组件关系(父子、兄弟、跨层级等)的不同,常用的传递方式主要有以下几种:

1. 父组件 → 子组件:Props

适用场景:最基础的父子组件通信,父组件向子组件传递数据。实现方式

  • 父组件在使用子组件时,通过属性绑定传递数据;
  • 子组件通过 props 声明接收的数据(类型、默认值等)。

示例(Script Setup 语法)

vue

<!-- 父组件 Parent.vue -->
<template><Child :message="parentMsg" :user="userInfo" />
</template>
<script setup>
import Child from './Child.vue'
const parentMsg = "来自父组件的消息"
const userInfo = { name: "张三", age: 20 }
</script><!-- 子组件 Child.vue -->
<template><div>{{ message }}</div><div>{{ user.name }}</div>
</template>
<script setup>
// 声明接收的props(支持类型校验、默认值等)
const props = defineProps({message: String,user: {type: Object,required: true}
})
// 使用:props.message 或直接在模板中使用
</script>

2. 子组件 → 父组件:自定义事件($emit)

适用场景:子组件向父组件传递数据(如用户操作反馈、表单提交等)。实现方式

  • 子组件通过 emit 触发自定义事件,并传递数据;
  • 父组件监听该事件,通过回调函数接收数据。

示例(Script Setup 语法)

vue

<!-- 子组件 Child.vue -->
<template><button @click="handleClick">传递数据给父组件</button>
</template>
<script setup>
// 声明可触发的事件(可选,增强类型提示)
const emit = defineEmits(['sendData', 'update'])const handleClick = () => {// 触发事件并传递数据emit('sendData', "来自子组件的消息")emit('update', { value: 100 })
}
</script><!-- 父组件 Parent.vue -->
<template><Child @sendData="handleReceive" @update="(data) => console.log('接收更新:', data)" />
</template>
<script setup>
const handleReceive = (msg) => {console.log("父组件收到:", msg) // 输出:"来自子组件的消息"
}
</script>

3. 深层级组件通信:Provide / Inject

适用场景:跨层级组件(如祖父→孙子,或更深层级)传递数据,避免 “props 逐级透传” 的冗余。实现方式

  • 父组件(或祖先组件)通过 provide 提供数据;
  • 子组件(或后代组件)通过 inject 注入并使用数据。

示例

vue

<!-- 祖先组件 Grandparent.vue -->
<script setup>
import { provide } from 'vue'
// 提供数据(可以是响应式数据)
provide('theme', 'dark')
provide('user', { name: "李四" })
</script><!-- 后代组件 Grandchild.vue -->
<template><div>主题:{{ theme }}</div><div>用户:{{ user.name }}</div>
</template>
<script setup>
import { inject } from 'vue'
// 注入数据(可指定默认值)
const theme = inject('theme', 'light') // 若未提供,使用默认值'light'
const user = inject('user')
</script>

注意provide/inject 默认是非响应式的,若需响应式,可传递 ref 或 reactive 对象。

4. 全局状态共享:Pinia(或 Vuex)

适用场景:多个组件(无直接层级关系)共享全局状态(如用户信息、购物车数据等)。说明

  • Pinia 是 Vue3 官方推荐的状态管理库,替代了 Vuex,API 更简洁;
  • 核心概念是 “Store”,集中管理状态,任何组件都可读写。

简单示例(Pinia)

js

// stores/cart.js(定义Store)
import { defineStore } from 'pinia'
export const useCartStore = defineStore('cart', {state: () => ({ items: [] }),actions: {addItem(item) {this.items.push(item)}}
})// 组件A(添加商品)
<script setup>
import { useCartStore } from './stores/cart'
const cartStore = useCartStore()
cartStore.addItem({ id: 1, name: "商品A" })
</script>// 组件B(显示购物车)
<template><div>购物车数量:{{ cartStore.items.length }}</div>
</template>
<script setup>
import { useCartStore } from './stores/cart'
const cartStore = useCartStore()
</script>

5. 兄弟组件 / 任意组件:全局事件总线(mitt)

适用场景:无直接关系的组件(如兄弟、跨多级)之间的简单通信。实现方式

  • Vue3 移除了内置的 $on/$off,需借助第三方库(如 mitt)实现全局事件监听;
  • 原理:创建一个全局事件中心,组件通过 “on” 监听事件,“emit” 触发事件。

示例

bash

# 安装mitt
npm install mitt

js

// utils/eventBus.js(创建全局事件总线)
import mitt from 'mitt'
export const eventBus = mitt()// 组件A(发送方)
<script setup>
import { eventBus } from './utils/eventBus'
const sendToBrother = () => {eventBus.emit('brother-event', "来自兄弟A的消息")
}
</script>// 组件B(接收方)
<script setup>
import { eventBus } from './utils/eventBus'
import { onMounted, onUnmounted } from 'vue'onMounted(() => {// 监听事件eventBus.on('brother-event', (msg) => {console.log("兄弟B收到:", msg)})
})onUnmounted(() => {// 移除监听(避免内存泄漏)eventBus.off('brother-event')
})
</script>

6. 父子组件直接访问:ref / $parent(不推荐)

适用场景:极少数特殊情况(如父组件需要直接调用子组件方法)。说明

  • 父组件通过 ref 获取子组件实例,直接访问其属性 / 方法;
  • 子组件通过 $parent 访问父组件实例(Vue3 中不推荐,易导致耦合)。

示例

vue

<!-- 父组件 Parent.vue -->
<template><Child ref="childRef" /><button @click="callChildMethod">调用子组件方法</button>
</template>
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'
const childRef = ref(null)const callChildMethod = () => {// 直接访问子组件的方法/属性childRef.value.childMethod() console.log(childRef.value.childMsg)
}
</script><!-- 子组件 Child.vue -->
<script setup>
import { ref } from 'vue'
const childMsg = ref("子组件的消息")
const childMethod = () => {console.log("子组件方法被调用")
}
// 暴露给父组件的属性/方法(Script Setup默认私有,需显式暴露)
defineExpose({ childMsg, childMethod })
</script>

注意:这种方式会增加组件耦合,优先使用 props/emit。

7. 路由参数传递(页面级组件)

适用场景:路由跳转时,页面级组件之间传递数据(如详情页接收列表页的 ID)。实现方式:通过路由参数(params 或 query)传递,新页面从路由中获取。

示例

js

// 路由配置(router/index.js)
const routes = [{ path: '/detail/:id', component: Detail }
]// 列表页(发送参数)
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
const goToDetail = (id) => {router.push(`/detail/${id}`) // 传递params// 或 router.push({ path: '/detail', query: { id } }) // 传递query
}
</script>// 详情页(接收参数)
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
console.log("接收的ID:", route.params.id) // 或 route.query.id
</script>

总结

选择哪种传递方式,主要看组件关系和场景:

  • 父子通信:优先用 props + 自定义事件
  • 深层级通信:用 provide/inject
  • 全局共享状态:用 Pinia
  • 无关系组件通信:用 全局事件总线(mitt)
  • 页面跳转:用 路由参数

避免过度使用 ref/$parent 或全局事件总线,以免导致组件耦合过高。

http://www.dtcms.com/a/469882.html

相关文章:

  • 掌握PINN:从理论到实战的神经网络进阶!!
  • wordpress thremeseo推广排名软件
  • 安平县哪里做网站建立公司网站视频
  • PostgreSql ALL 与 ANY 区别
  • 解决 husky > pre-commit hook failed (add --no-verify to bypass)
  • 模拟器抓包
  • (数据结构)线性表(下):链表分类及双向链表的实现
  • 阿里云短信服务配置说明
  • Java+SpringBoot+Dubbo+Nacos快速入门
  • 【开题答辩全过程】以 办公管理系统为例,包含答辩的问题和答案
  • 天创网站做网站 数据标准
  • 做除尘骨架的网站网页一般用什么语言编写
  • SciPy 常量模块
  • 记录一次在Win7系统中使用C#中的HttpWebRequest连接缓慢、超时等问题(httpclient和restsharp也存在同样的问题)
  • Spring Boot 3零基础教程,Spring Intializer,笔记05
  • spring boot 2.x 与 spring boot 3.x 及对应Tomcat、Jetty、Undertow版本的选择(理论)
  • 织梦 网站栏目管理 很慢国内免费域名申请
  • 建设企业网站的好处是什么门户网站建设的成果
  • 【BUG排查】基于RH850F1KMS1的主控出现系统中断错误,调试FEIC的值为0x11
  • C++变量命名详解
  • 2.c++面向对象(三)
  • 自动化测试系统Parasoft航空设备行业案例:减少75%的BUG
  • Git Commit Message 最佳实践:从一次指针Bug说起
  • 网站设计专业知识技能传奇 网页游戏排行榜
  • 漳州北京网站建设公司wordpress小工具九宫格
  • 多智能体协作中的数据交互艺术:构建高效协同的智能系统
  • 人工智能大模型的“通俗理解”
  • 网站后台怎么做水印图片石家庄最新大事
  • 项目学习总结:platform方式驱动框架、pc版和arm版连通ONENET方式、wireshark抓包mqtt、ONENET创建产品、双网卡配置
  • Transformers包常用函数讲解