在Vue组件通信中,灵活选择合适的方式能大幅提升开发效率。以下是常用的组件传值方式,按场景分类整理:
---
### 一、父子组件通信
1. **Props(父 → 子)**
父组件通过属性传递数据,子组件用`props`接收。
```vue
<!-- 父组件 -->
<Child :message="parentMsg" />
<!-- 子组件 -->
<script>
export default { props: ['message'] }
</script>
```
2. **$emit(子 → 父)**
子组件触发自定义事件,父组件监听。
```vue
<!-- 子组件 -->
<button @click="$emit('notify', data)">通知父组件</button>
<!-- 父组件 -->
<Child @notify="handleNotify" />
```
3. **.sync修饰符(双向绑定)**
Vue 2.3+ 提供,简化双向绑定语法。
```vue
<!-- 父组件 -->
<Child :title.sync="pageTitle" />
<!-- 子组件 -->
<script>
this.$emit('update:title', newTitle)
</script>
```
4. **v-model(表单/自定义组件)**
语法糖,默认监听`input`事件和绑定`value`属性。
```vue
<!-- 父组件 -->
<Child v-model="inputValue" />
<!-- 子组件 -->
<input :value="value" @input="$emit('input', $event.target.value)" />
```
---
### 二、跨层级通信
5. **$attrs 和 $listeners(透传属性/事件)**
`$attrs`传递未在`props`中声明的属性,`$listeners`传递所有事件监听器。
```vue
<!-- 中间组件 -->
<Grandchild v-bind="$attrs" v-on="$listeners" />
```
6. **provide/inject(依赖注入)**
祖先组件提供数据,后代组件注入使用。
```vue
<!-- 祖先组件 -->
<script>
export default { provide() { return { theme: 'dark' } } }
</script>
<!-- 后代组件 -->
<script>
export default { inject: ['theme'] }
</script>
```
---
### 三、全局/跨组件通信
7. **Event Bus(事件总线)**
创建一个全局Vue实例作为事件中心。
```js
// bus.js
import Vue from 'vue'
export const bus = new Vue()
// 组件A发送事件
bus.$emit('event-name', data)
// 组件B监听事件
bus.$on('event-name', data => { ... })
```
8. **Vuex(状态管理)**
集中式状态管理,适合中大型应用。
```js
// store.js
export default new Vuex.Store({ state: { count: 0 } })
// 组件中访问
this.$store.state.count
```
---
### 四、直接访问组件实例
9. **$parent / $children**
通过父子实例直接访问,但耦合性高。
```js
// 子组件访问父组件
this.$parent.parentMethod()
// 父组件访问第一个子组件
this.$children[0].childMethod()
```
10. **$refs**
通过`ref`属性标记,直接调用子组件方法。
```vue
<!-- 父组件 -->
<Child ref="childRef" />
<script>
this.$refs.childRef.doSomething()
</script>
```
---
### 五、特殊场景通信
11. **作用域插槽(子 → 父传递数据)**
子组件通过插槽暴露数据,父组件接收使用。
```vue
<!-- 子组件 -->
<slot :user="userData"></slot>
<!-- 父组件 -->
<Child>
<template v-slot:default="slotProps">{{ slotProps.user }}</template>
</Child>
```
12. **路由参数(URL传参)**
通过路由配置传递参数。
```js
// 路由配置
{ path: '/user/:id', component: User }
// 组件中获取
this.$route.params.id
```
---
### 选择建议
- **简单父子通信**:`props` + `$emit`
- **跨层级/复杂场景**:`provide/inject`、`Event Bus`、`Vuex`
- **快速原型开发**:`$refs`或`.sync`
- **状态共享**:优先考虑`Vuex`或`Pinia`(Vue 3)
根据项目规模和需求选择最合适的方式,避免过度设计。