【Vue3】【笔记】----第四章:Vue3 组件通信(从基础到复杂场景)
·
第四章:Vue3 组件通信(从基础到复杂场景)
一、入门:组件通信的核心场景与基础方式
- 组件关系与通信需求:Vue项目中组件主要有“父子关系”“兄弟关系”“跨层级关系”,其中父子通信是最基础、最常用的场景,需优先掌握。
- 父子通信两种核心方式:
- 父传子(Props):父组件通过“自定义属性”向子组件传值,子组件用
defineProps声明接收的属性及类型,例:- 父组件:
<TodoItem :todo="item" :index="index" />(传递todo对象和index数字) - 子组件:
const props = defineProps({ todo: Object, index: Number })(声明后直接用props.todo访问)
- 父组件:
- 子传父(Emit):子组件通过“自定义事件”向父组件传值,子组件用
defineEmits声明事件,父组件用@事件名监听,例:- 子组件:
const emit = defineEmits(['delete']),点击删除时执行emit('delete', props.index)(传递索引值) - 父组件:
<TodoItem @delete="handleDelete" />,定义handleDelete(index)函数处理删除逻辑
- 子组件:
- 父传子(Props):父组件通过“自定义属性”向子组件传值,子组件用
二、精通:进阶通信方式与场景适配
- 跨层级通信(解决“祖孙组件”通信痛点):
provide/inject:父组件用provide提供数据,所有子组件(无论层级)用inject接收,无需层层传递Props,例:- 父组件:
import { provide } from 'vue',provide('themeColor', 'blue')(提供主题色) - 孙组件:
import { inject } from 'vue',const themeColor = inject('themeColor', 'white')(接收,默认值white)
- 父组件:
- 注意:
provide/inject不推荐用于频繁更新的数据(如需响应式,需传递ref/reactive对象),更适合传递“静态配置”(如主题、权限)。
- 兄弟组件通信(两种方案选其一):
- 父组件中转:通过“子传父→父传子”的链路,借助父组件作为中间层,适合简单场景(如两个兄弟组件联动)。
- 事件总线(mitt):Vue3移除了
$on/$off,需用第三方库mitt,创建全局事件中心,兄弟组件通过“发布-订阅”通信,例:- 安装:
npm install mitt - 创建总线:
// utils/bus.js,import mitt from 'mitt',export default mitt() - 发送方:
import bus from './utils/bus',bus.emit('todoUpdate', newData)(发布事件) - 接收方:
bus.on('todoUpdate', (data) => { console.log('接收数据:', data) })(订阅事件)
- 安装:
- 全局状态通信:当多个组件(无直接关系)需要共享数据(如用户信息、购物车),需用“状态管理工具”(如Pinia),后续章节单独详解。
三、实战:多组件通信实现“商品筛选功能”
- 需求拆解:页面包含“筛选条件组件(Filter)”“商品列表组件(GoodsList)”“筛选结果统计组件(ResultCount)”,需实现:Filter选择条件→GoodsList显示筛选后商品→ResultCount统计数量,三者为“兄弟关系”。
- 通信方案:用“父组件(GoodsPage)中转+Props/Emit”实现,步骤如下:
- 父组件:定义响应式数据
filterParams(筛选条件,如价格区间、分类)和filteredGoods(筛选后商品),作为数据中心。 - Filter→父组件:Filter用
emit将选择的筛选条件传给父组件,父组件接收后更新filterParams,并执行筛选逻辑更新filteredGoods。 - 父组件→GoodsList/ResultCount:父组件通过
Props将filteredGoods传给GoodsList(渲染列表),将filteredGoods.length传给ResultCount(显示数量)。
- 父组件:定义响应式数据
- 代码核心逻辑:
- 父组件:
const filterParams = reactive({ priceMin: 0, category: 'all' }),const filteredGoods = computed(() => goodsList.filter(item => item.price >= filterParams.priceMin && (filterParams.category === 'all' || item.category === filterParams.category))) - Filter组件:
emit('updateFilter', { priceMin: 100, category: 'phone' }) - 父组件监听:
<Filter @updateFilter="(params) => Object.assign(filterParams, params)" />
- 父组件:
更多推荐
所有评论(0)