vue3组件间通信方式
一.前言在 Vue3 项目中组件化是核心思想。随着业务复杂度提升组件之间不可避免地需要进行数据与行为的通信。合理选择通信方式不仅能让代码更清晰、可维护性更高也能显著降低后期重构成本。本文将系统性地梳理Vue3中常见且实用的组件间通信方式结合典型使用场景、代码示例及优缺点分析帮助开发者在实际项目中做出正确选择。二. 通信1.父子组件通信Props / Emits1.1 父组件向子组件传值Props父组件通过 props 向子组件传递数据这是最基础、也是最推荐的单向数据流方式。!-- Parent.vue -- Child :titlepageTitle / !-- Child.vue -- script setup const props defineProps({ title: String }) /script1.2 子组件向父组件传值Emits子组件通过 emit 触发事件将数据回传给父组件。!-- Parent.vue -- Child updatehandleUpdate / !-- Child.vue -- script setup const emit defineEmits([update]) function handleClick() { emit(update, new value) } /script2.v-model 语法糖双向绑定通信2.1 默认v-model!-- Parent.vue -- Child v-modelvalue / !-- Child.vue -- el-input v-modelinnerValue change” handleChange / script setup const props defineProps({ modelValue: String }) const emit defineEmits([update:modelValue]) function handleChange(){ emit(update:modelValue, innerValue); } /script2.2 多个v-model!-- Parent.vue -- Child v-model:titletitle v-model:visiblevisible / !-- 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) } /script3.祖先/后代组件通信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:keywordkeyword / ResultTable :keywordkeyword / /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 :valuekeyword inputonInput placeholder请输入关键字 / /template !-- ResultTable.vue -- script setup const props defineProps({ keyword: String }) /script template div 当前筛选条件{{ keyword }} /div /template4.2使用全局状态如 Pinia适用于复杂业务、多个模块共享数据的场景。具体使用详见 5.全局状态管理5.全局状态管理Piniastore.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 langts import { useArrangeStore } from /stores/index.ts; const arrangeStore useArrangeStore(); function handleSend(){ arrangeStore.setArrangeData(tableData); } /script // 组件中使用 接收方 script setup langts import { useArrangeStore } from /stores/index.ts; const arrangeStore useArrangeStore(); function handleRecive(){ console.log(arrangeStore.arrangeData); } /script6.ref / expose父组件直接调用子组件方法!-- Child.vue -- script setup defineExpose({ reset }) /script !-- Parent.vue -- Child refchildRef/Child script setup const childRef ref() childRef?.value.reset() /script7.通信方式对比与选型建议场景推荐方式特点父-子props单向数据流、数据来源清晰、适合展示型、受控组件子-父emits明确的数据回流路径、适合表单或交互组件子-父v-model表单组件、弹窗、抽屉等状态控制组件跨多层级provide / inject跨层级传递数据、避免 props 层层透传、不适合频繁变化的数据默认非响应式除非用ref等全局状态Pinia跨页面、跨模块状态共享、登录信息、权限信息、全局配置调用子方法ref expose表单重置、强制刷新、复用校验等操作三.总结Vue3 提供了多种组件通信方式各有其适用场景。遵循以下原则通常能写出更优雅的代码能用 props / emits就不要上全局状态数据流向要清晰、可追踪避免滥用 provide / inject 和命令式调用合理选择通信方案是 Vue3 项目长期可维护的关键。