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

vue3组件间通信方式

一.前言

在 Vue3 项目中组件化是核心思想。随着业务复杂度提升,组件之间不可避免地需要进行数据与行为的通信。合理选择通信方式,不仅能让代码更清晰、可维护性更高,也能显著降低后期重构成本。

本文将系统性地梳理Vue3中常见且实用的组件间通信方式,结合典型使用场景、代码示例及优缺点分析,帮助开发者在实际项目中做出正确选择。

二. 通信

1.父子组件通信(Props / Emits)

1.1 父组件向子组件传值(Props)

父组件通过 props 向子组件传递数据,这是最基础、也是最推荐的单向数据流方式。

<!-- Parent.vue --> <Child :title="pageTitle" /> <!-- Child.vue --> <script setup> const props = defineProps({ title: String }) </script>

1.2 子组件向父组件传值(Emits)

子组件通过 emit 触发事件,将数据回传给父组件。

<!-- Parent.vue --> <Child @update="handleUpdate" /> <!-- Child.vue --> <script setup> const emit = defineEmits(['update']) function handleClick() { emit('update', 'new value') } </script>

2.v-model 语法糖(双向绑定通信)

2.1 默认v-model

<!-- Parent.vue --> <Child v-model="value" /> <!-- Child.vue --> <el-input v-model="innerValue" @change=” handleChange /> <script setup> const props = defineProps({ modelValue: String }) const emit = defineEmits(['update:modelValue']) function handleChange(){ emit("update:modelValue", innerValue); } </script>

2.2 多个v-model

<!-- Parent.vue --> <Child v-model:title="title" v-model:visible="visible" /> <!-- Child.vue --> <script setup> const props = defineProps({ title: String, visible: Boolean }) const emit = defineEmits([ 'update:title', 'update:visible' ]) function changeTitle(newTitle) { emit('update:title', newTitle) } function open() { emit('update:visible', true) } function close() { emit('update:visible', false) } </script>

3.祖先/后代组件通信(Provide/Inject)

// 祖先组件

provide('theme', 'dark')

// 后代组件 <setup>中直接用,其他函数引用这个获取的常量值themeNew ,不能直接引用 //inject('theme')

const themeNew = inject('theme')

注意: 如果多个祖先provide('theme', value), 后代inject得到的值为最近祖先provide的值

4.兄弟组件通信

4.1借助父组件中转

兄弟组件之间不直接通信,通过父组件统一管理状态。

<!-- Parent.vue --> <script setup> import { ref } from 'vue' import FilterPanel from './FilterPanel.vue' import ResultTable from './ResultTable.vue' const keyword = ref('') </script> <template> <FilterPanel v-model:keyword="keyword" /> <ResultTable :keyword="keyword" /> </template> <!-- FilterPanel.vue --> <script setup> const props = defineProps({ keyword: String }) const emit = defineEmits(['update:keyword']) function onInput(e) { emit('update:keyword', e.target.value) } </script> <template> <input :value="keyword" @input="onInput" placeholder="请输入关键字" /> </template> <!-- ResultTable.vue --> <script setup> const props = defineProps({ keyword: String }) </script> <template> <div> 当前筛选条件:{{ keyword }} </div> </template>

4.2使用全局状态(如 Pinia)

适用于复杂业务、多个模块共享数据的场景。具体使用详见 5.全局状态管理

5.全局状态管理(Pinia)

store.js 定义Store import { defineStore } from "pinia"; import { ArrangeInfo } from "@/const/commonModelEntity"; // 排列信息store export const useArrangeStore = defineStore("arrange", { state: (): { arrangeData: ArrangeInfo[] } => ({ arrangeData: [], // 排列信息 }), actions: { setArrangeData(data: ArrangeInfo[]) { this.arrangeData = data; }, }, }); // 组件中使用 发送方 <script setup lang="ts"> import { useArrangeStore } from "@/stores/index.ts"; const arrangeStore = useArrangeStore(); function handleSend(){ arrangeStore.setArrangeData(tableData); } </script> // 组件中使用 接收方 <script setup lang="ts"> import { useArrangeStore } from "@/stores/index.ts"; const arrangeStore = useArrangeStore(); function handleRecive(){ console.log(arrangeStore.arrangeData); } </script>

6.ref / expose(父组件直接调用子组件方法)

<!-- Child.vue --> <script setup> defineExpose({ reset }) </script> <!-- Parent.vue --> <Child ref=childRef></Child> <script setup> const childRef = ref() childRef?.value.reset() </script>

7.通信方式对比与选型建议

场景

推荐方式

特点

父->子

props

单向数据流、数据来源清晰、适合展示型、受控组件

子->父

emits

明确的数据回流路径、适合表单或交互组件

子->父

v-model

表单组件、弹窗、抽屉等状态控制组件

跨多层级

provide / inject

跨层级传递数据、避免 props 层层透传、不适合频繁变化的数据(默认非响应式)除非用ref等

全局状态

Pinia

跨页面、跨模块状态共享、登录信息、权限信息、全局配置

调用子方法

ref + expose

表单重置、强制刷新、复用校验等操作

三.总结

Vue3 提供了多种组件通信方式,各有其适用场景。遵循以下原则通常能写出更优雅的代码:

  • 能用 props / emits,就不要上全局状态

  • 数据流向要清晰、可追踪

  • 避免滥用 provide / inject 和命令式调用

合理选择通信方案,是 Vue3 项目长期可维护的关键。

http://www.jsqmd.com/news/622482/

相关文章:

  • 永嘉原厂超抗干扰/抗静电LCD驱动IC超小封装段码液晶屏驱动芯片VK2C21AQ QFN28/DICE/COG
  • MongoDB为什么会选错索引_查询优化器计划缓存(Plan Cache)清理
  • 一个免费、轻量的 Typora 图床方案:Cloudflare R2 + Python——十分钟完成
  • 基于Verilog的以太网PHY芯片MDIO寄存器自动化测试方案
  • 最佳复古游戏体验设置
  • .NET 诊断技巧 | 日志框架原理、手写日志框架学习蒂
  • live-plugin-manager nodejs 插件框架
  • .NET源码生成器基于partial范式开发和nuget打包衷
  • 基于django外语学习系统
  • VMware macOS虚拟机终极解锁指南:如何3分钟启用苹果系统支持
  • Z-Image-Turbo-辉夜巫女效果展示:高还原度巫女形象+细腻光影+日式构图
  • PDF提取不求人:MinerU镜像开箱即用,支持GPU加速
  • 盘点类似问卷星的软件有哪些:题型丰富度+样本服务(防坑必看) - 品牌排行榜
  • 【Verilog】阻塞/非阻塞赋值
  • 记一次综合型流量分析 | 添柴不加火拦
  • **Pandas实战进阶:用DataFrame的“变形术”解锁数据清洗与分析新姿势**在数
  • 告别马赛克!用PyTorch和ESRGAN亲手复活你的老照片(附完整代码与数据集处理技巧)
  • YOLO11新手入门:5分钟学会训练自己的目标检测模型
  • Keyviz:终极键鼠可视化工具,让你的操作清晰可见
  • 质量工程师首选丨DOE实验设计软件盘点:信创认证平台(选型指南) - 品牌排行榜
  • [第五空间 2021]WebFTP
  • Meta押注“超级智能”:Muse Spark横空出世,扎克伯格的AI翻身仗打响了
  • Trae与Gitee MCP无缝协作:AI编程工具链的智能化革命
  • 利用Python API高效批量获取ECMWF大气数据:从注册到自动化下载全流程
  • 如何在Flash退役时代依然畅玩经典游戏?CefFlashBrowser的3大核心功能解密
  • Elsevier审稿追踪插件:5分钟告别手动刷新,实现智能投稿监控
  • 2026 智能会议系统哪个品牌好?世邦通信成政企首选
  • 反垃圾邮件网关厂商排名:建议参考第三方独立测试报告而非单纯市场调研 - 品牌排行榜
  • 1.2 环境搭建与项目结构
  • E-Hentai-Downloader 终极指南:如何快速批量下载漫画并打包为ZIP文件