Vue3组件通信方式选择指南

一、父子组件通信

1. Props + Events(最基础)
  • 适用场景:父子组件直接传递数据(父传子用 props,子传父用 emit)。

  • 优点:符合单向数据流,逻辑清晰。

  • 示例

    vue

    <!-- 父组件 -->
    <Child :value="parentData" @update="handleUpdate" />
    
    <!-- 子组件 -->
    <script setup>
    const props = defineProps(['value']);
    const emit = defineEmits(['update']);
    emit('update', newValue);
    </script>
2. v-model(语法糖)
  • 适用场景:简化表单类组件的双向绑定。

  • 原理v-model 是 :modelValue + @update:modelValue 的语法糖。

  • 示例

    vue

    <!-- 父组件 -->
    <Child v-model="data" />
    
    <!-- 子组件 -->
    <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />

二、跨层级组件通信

1. Provide/Inject
  • 适用场景:祖先组件向后代组件传递数据(无需逐层传递)。

  • 优点:适合全局配置(如主题、用户信息)、深层嵌套组件。

  • 示例

    vue

    <!-- 祖先组件 -->
    <script setup>
    import { provide } from 'vue';
    provide('theme', 'dark');
    </script>
    
    <!-- 后代组件 -->
    <script setup>
    import { inject } from 'vue';
    const theme = inject('theme', 'light'); // 默认值 'light'
    </script>
2. 状态管理(Pinia/Vuex)
  • 适用场景:复杂应用的多组件共享状态(如用户登录态、购物车)。

  • 优点:集中管理状态,支持响应式、调试工具。

  • 推荐:Vue 3 首选 Pinia(更简洁,替代 Vuex)。

  • 示例

    js

    // store/counter.js
    export const useCounterStore = defineStore('counter', {
      state: () => ({ count: 0 }),
      actions: {
        increment() { this.count++ }
      }
    });
    
    // 组件中使用
    const counter = useCounterStore();
    counter.increment();

三、兄弟组件/无直接关系组件

1. 状态管理(Pinia/Vuex)
  • 适用场景:兄弟组件共享数据或跨组件通信。

  • 优点:解耦组件,状态可追踪。

2. 事件总线(谨慎使用)
  • 适用场景:小型项目快速实现通信(Vue 3 需借助第三方库如 mitt)。

  • 缺点:事件流难追踪,大型项目慎用。

  • 示例

    js

    // eventBus.js
    import mitt from 'mitt';
    export const emitter = mitt();
    
    // 组件 A 发送事件
    emitter.emit('event-name', data);
    
    // 组件 B 监听事件
    emitter.on('event-name', (data) => { ... });

四、直接操作组件

1. 模板引用(Template Refs)
  • 适用场景:父组件直接调用子组件方法或访问 DOM。

  • 示例

    vue

    <!-- 父组件 -->
    <Child ref="childRef" />
    <script setup>
    import { ref } from 'vue';
    const childRef = ref(null);
    childRef.value.someMethod();
    </script>
    
    <!-- 子组件 -->
    <script setup>
    defineExpose({ someMethod: () => { ... } });
    </script>

选择策略总结

场景推荐方式
父子组件props + emitv-model
深层嵌套组件provide/inject
兄弟/无关系组件Pinia(状态管理)
全局共享状态Pinia(如用户信息、主题)
简单快速通信事件总线(小型项目)
直接操作子组件模板引用(ref + defineExpose

注意事项

  1. 避免过度使用事件总线:易导致代码混乱,优先考虑状态管理。

  2. 保持单向数据流:子组件不要直接修改 props,应通过事件通知父组件。

  3. 合理分层:简单场景用 props/emit,复杂场景用状态管理。

根据项目规模和组件关系选择最简洁的方案,避免过度设计!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值