props
-
模式:单项数据传递(父传子)
-
定义:
props
是父组件向子组件传递数据的机制。它是单向绑定,父组件数据更新,子组件自动响应。子组件不能更新props
里的数据,只能读取。 -
示例:
- 父组件
js<template> <div class="parent">{{ username }}</div> <Children :title='title' /> </template> <script setup> import Child from './Child.vue'; const username = '王五' const title = '文章标题' </script>
- 子组件
js<template> <div class="child">{{ title }}</div> </template> <script setup> const props = defineProps({ title: { type: String, default: "" } }) </script>
-
原理:
- Vue 在父组件渲染子组件时,会将绑定的数据以属性形式传递给子组件,子组件根据
props
定义接收这些值,并通过 Vue 的响应式系统追踪这些数据的变化。 - 在 Vue 3 中,
props
是浅层响应式(shallowReactive
)且只读的,确保单向数据流。当父组件更新传入的 prop 时,Vue 会自动触发子组件的更新,从而实现组件间的数据传递与响应式联动。
- Vue 在父组件渲染子组件时,会将绑定的数据以属性形式传递给子组件,子组件根据
-
使用场景:
- 父组件向子组件传递数据
- 传递静态/响应式参数
- 控制子组件行为(如
v-model
的modelValue
)
-
优点:
- 简单直观,符合组件设计原则
- 支持类型校验、默认值、必传限制等
- 与 Vue 的响应式机制天然集成
-
缺点
- 只能单向数据传递
- 深层组件嵌套时容易传递链条过长
prop drilling
provide/inject
-
模式:祖先 -> 后代(跨多层)
-
定义:
provide
和inject
是vue
的跨层级组件传值机制。祖先组件提供数据,后代组件都可注入使用,无需中间组件传递。 -
示例
- 祖先组件
js<template> <div class="parent">{{ username }}</div> <Children /> </template> <script setup> import Child from './Child.vue'; import { provide } from "vue"; const username = '王五' const title = '文章标题' provide('parentState', { title, username }) </script>
- 后代组件
js<template> <div class="child">{{ parentState.title.value }}</div> </template> <script setup> import { inject } from "vue"; const parentState = inject('parentState') </script>
-
原理:
provide
会将一个对象注入到vue
的依赖注入系统中,inject
会从祖先组件的provide
中查找对应的key
。 -
使用场景:
- 跨层级配置传递(如主题、国际化、表单上下文)
- 插槽中组件共享上下文(如 Ant Design 的 Form.Item)
-
优点:
- 避免了
prop drilling
- 可以跨层级传递,更灵活
vue3
中支持响应式provide
- 避免了
-
缺点:
- 祖先和后代高度耦合,不容易追踪数据来源
- 不适合频繁变更的响应式通信(Vue 2 中不是响应式的,Vue 3 支持)
- 不适合兄弟组件通信
eventBus
-
模式:任意组件之间通信
-
定义:eventbus是通过mitt实例来充当事件总线,组件通过它来监听、触发事件,解耦通信对象之间的直接关系。
-
示例
- 定义eventBus文件
jsimport mitt from 'mitt' const emitter = mitt() export default emitter
- 发布事件
js<template> <div>{{ username }}</div> <button @click='handleToggleName'> </template> <script setup> import emitter from "./eventBus"; const username = ref('') const handleToggleName = () => { username.value = '王五' // 发布事件 emitter.emit('UseNameChange', {username: username.value}) } </script>
- 订阅事件
js<template> <div>兄弟组件</div> <button @click='handleSubmit'> </template> <script setup> import emitter from "./eventBus"; const handleSubmit = (parmas) => { console.log(parmas.username, '更新之后的username') } onMounted(() => { // 订阅事件 emitter.on('UseNameChange', handleSubmit) }) onBeforeUnmount(() => { // 避免内存泄露,组件销毁时注销事件 emitter.off('UseNameChange', handleSubmit); }); </script>
-
原理:
eventBus
本质上是发布-订阅模式。每个事件注册一组回调函数,某个组件触发事件时,会调用所有注册的回调 -
使用场景:
- 任意组件之间通信(兄弟组件通信)
- 解耦组件
- 低频事件通知(如:弹窗控制、全局登录状态等)
-
优点:
- 无需组件嵌套关系,灵活自由
- 快速实现组件间通信
- 尤其适用于中小型项目
-
缺点:
- 事件追踪困难(不易维护)
- 内存泄漏风险(未移除监听器)
- 不利于大型项目架构(推荐用 Vuex 或 Pinia 替代)
...待更新