【Vue3知识】组件间通信的方式

组件间通信的方式

概述

在 Vue 3 中,组件间通信是一个常见且重要的需求。Vue 3 提供了多种方式来实现组件间的通信,根据组件的关系(父子组件、兄弟组件、跨层级组件等)和具体需求,可以选择不同的通信方式。以下是一些常用的组件间通信方法:

1. 父子组件通信

父组件向子组件传递数据(Props)
  • 使用 props :父组件通过 props 向子组件传递数据。

  • 示例

    vue 复制代码
    <!-- ParentComponent.vue -->
    <template>
      <ChildComponent :message="parentMessage" />
    </template>
    
    <script>
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      components: { ChildComponent },
      data() {
        return {
          parentMessage: 'Hello from Parent',
        };
      },
    };
    </script>
    vue 复制代码
    <!-- ChildComponent.vue -->
    <template>
      <div>{{ message }}</div>
    </template>
    
    <script>
    export default {
      props: {
        message: {
          type: String,
          required: true,
        },
      },
    };
    </script>
子组件向父组件发送事件(自定义事件)
  • 使用 $emit :子组件通过 $emit 触发事件,父组件监听该事件并处理。

  • 示例

    vue 复制代码
    <!-- ParentComponent.vue -->
    <template>
      <ChildComponent @update="handleUpdate" />
    </template>
    
    <script>
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      components: { ChildComponent },
      methods: {
        handleUpdate(newMessage) {
          console.log('Received from child:', newMessage);
        },
      },
    };
    </script>
    vue 复制代码
    <!-- ChildComponent.vue -->
    <template>
      <button @click="sendMessage">Send Message</button>
    </template>
    
    <script>
    export default {
      methods: {
        sendMessage() {
          this.$emit('update', 'Hello from Child');
        },
      },
    };
    </script>

2. 兄弟组件通信

兄弟组件之间没有直接的通信机制,通常通过共同的父组件或状态管理工具实现。

通过父组件中转
  • 父组件作为中介:兄弟组件通过父组件传递数据或事件。

  • 示例

    vue 复制代码
    <!-- ParentComponent.vue -->
    <template>
      <SiblingOne @send-to-sibling="handleSiblingOneMessage" />
      <SiblingTwo :message="siblingTwoMessage" />
    </template>
    
    <script>
    import SiblingOne from './SiblingOne.vue';
    import SiblingTwo from './SiblingTwo.vue';
    
    export default {
      components: { SiblingOne, SiblingTwo },
      data() {
        return {
          siblingTwoMessage: '',
        };
      },
      methods: {
        handleSiblingOneMessage(message) {
          this.siblingTwoMessage = message;
        },
      },
    };
    </script>
    vue 复制代码
    <!-- SiblingOne.vue -->
    <template>
      <button @click="sendMessage">Send to Sibling Two</button>
    </template>
    
    <script>
    export default {
      methods: {
        sendMessage() {
          this.$emit('send-to-sibling', 'Hello from Sibling One');
        },
      },
    };
    </script>
    vue 复制代码
    <!-- SiblingTwo.vue -->
    <template>
      <div>{{ message }}</div>
    </template>
    
    <script>
    export default {
      props: {
        message: {
          type: String,
          default: '',
        },
      },
    };
    </script>
使用全局状态管理(如 Pinia 或 Vuex)
  • Pinia:Vue 3 推荐的状态管理库,用于管理全局状态。

  • 示例

    bash 复制代码
    # 安装 Pinia
    npm install pinia
    javascript 复制代码
    // store.js
    import { defineStore } from 'pinia';
    
    export const useMainStore = defineStore('main', {
      state: () => ({
        sharedMessage: '',
      }),
      actions: {
        setMessage(message) {
          this.sharedMessage = message;
        },
      },
    });
    vue 复制代码
    <!-- SiblingOne.vue -->
    <template>
      <button @click="sendMessage">Send to Sibling Two</button>
    </template>
    
    <script>
    import { useMainStore } from './store';
    
    export default {
      setup() {
        const store = useMainStore();
    
        const sendMessage = () => {
          store.setMessage('Hello from Sibling One');
        };
    
        return { sendMessage };
      },
    };
    </script>
    vue 复制代码
    <!-- SiblingTwo.vue -->
    <template>
      <div>{{ sharedMessage }}</div>
    </template>
    
    <script>
    import { computed } from 'vue';
    import { useMainStore } from './store';
    
    export default {
      setup() {
        const store = useMainStore();
    
        const sharedMessage = computed(() => store.sharedMessage);
    
        return { sharedMessage };
      },
    };
    </script>

3. 跨层级组件通信

使用 Provide/Inject
  • provideinject:Vue 3 提供的 API,用于在组件树中跨层级传递数据。

  • 示例

    vue 复制代码
    <!-- GrandParentComponent.vue -->
    <template>
      <ParentComponent />
    </template>
    
    <script>
    import { provide } from 'vue';
    import ParentComponent from './ParentComponent.vue';
    
    export default {
      components: { ParentComponent },
      setup() {
        provide('sharedData', 'Hello from GrandParent');
      },
    };
    </script>
    vue 复制代码
    <!-- ParentComponent.vue -->
    <template>
      <ChildComponent />
    </template>
    
    <script>
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      components: { ChildComponent },
    };
    </script>
    vue 复制代码
    <!-- ChildComponent.vue -->
    <template>
      <div>{{ injectedData }}</div>
    </template>
    
    <script>
    import { inject } from 'vue';
    
    export default {
      setup() {
        const injectedData = inject('sharedData');
    
        return { injectedData };
      },
    };
    </script>
使用全局事件总线(不推荐)
  • 事件总线:通过一个空的 Vue 实例作为事件总线,在组件间发送和接收事件。
  • 缺点:不推荐在 Vue 3 中使用,因为会导致组件间耦合度增加,难以维护。

4. 使用 Vue Router 的参数

  • 路由参数:通过路由参数在组件间传递数据。

  • 示例

    javascript 复制代码
    // router/index.js
    import { createRouter, createWebHistory } from 'vue-router';
    import ComponentA from './ComponentA.vue';
    import ComponentB from './ComponentB.vue';
    
    const routes = [
      { path: '/component-a', component: ComponentA },
      { path: '/component-b/:message', component: ComponentB },
    ];
    
    const router = createRouter({
      history: createWebHistory(),
      routes,
    });
    
    export default router;
    vue 复制代码
    <!-- ComponentA.vue -->
    <template>
      <button @click="navigateToB">Go to Component B</button>
    </template>
    
    <script>
    import { useRouter } from 'vue-router';
    
    export default {
      setup() {
        const router = useRouter();
    
        const navigateToB = () => {
          router.push({ path: '/component-b/Hello from Component A' });
        };
    
        return { navigateToB };
      },
    };
    </script>
    vue 复制代码
    <!-- ComponentB.vue -->
    <template>
      <div>{{ $route.params.message }}</div>
    </template>

总结

  • 父子组件 :使用 props$emit
  • 兄弟组件:通过父组件中转或使用状态管理工具。
  • 跨层级组件 :使用 provide/inject
  • 全局状态:使用 Pinia 或 Vuex。
  • 路由参数:通过 Vue Router 传递参数。

选择合适的通信方式可以提高代码的可维护性和可扩展性。在 Vue 3 中,推荐优先使用 props$emitprovide/inject,并在需要全局状态管理时使用 Pinia。

关联知识

【Vue3知识】Vue3父子组件间数据通信

相关推荐
Mintopia几秒前
像素的进化史诗:计算机图形学与屏幕的千年之恋
前端·javascript·计算机图形学
蓝桉(努力版)2 分钟前
MATLAB可视化5:华夫图(饼图的平替可以表示种类的分布,附有完整代码详细讲解)(求个关注、点赞和收藏)(对配色不满意可以自己调节配色,附调色教程)
开发语言·数学建模·matlab·信息可视化·matlab可视化
Mintopia3 分钟前
Three.js 中三角形到四边形的顶点变换:一场几何的华丽变身
前端·javascript·three.js
归于尽17 分钟前
async/await 从入门到精通,解锁异步编程的优雅密码
前端·javascript
艾莉丝努力练剑18 分钟前
【C语言】学习过程教训与经验杂谈:思想准备、知识回顾(五)
c语言·开发语言·数据结构·学习·算法
云空19 分钟前
《QtPy:Python与Qt的完美桥梁》
开发语言·python·qt·pyqt
晓131334 分钟前
JavaScript加强篇——第六章 定时器(延时函数)与JS执行机制
开发语言·javascript·ecmascript
wh_xia_jun1 小时前
基于 Python 的数据分析技术综述
开发语言·python·数据分析
yanlele1 小时前
【实践篇】【01】我用做了一个插件, 点击复制, 获取当前文章为 Markdown 文档
前端·javascript·浏览器
LeeAt1 小时前
手把手教你构建自己的MCP服务器并把它连接到你的Cursor
javascript·cursor·mcp