Vue3 跨组件传递数据

737 阅读3分钟

概述

Vue 3 中跨组件传递数据有多种策略,根据组件间的关系和通信需求,可以选择最合适的方式。 以下是几种常见的数据传递方法:

  • Props (父传子)

    最基本的方式,用于从父组件向子组件传递数据。在子组件中定义props对象来接收数据,父组件通过v-bind或简写为冒号:来绑定属性值。

  • Emit (子传父)

    子组件通过触发事件向上通知父组件。子组件使用emit函数触发一个事件,父组件则在子组件标签上监听这个事件。

  • Provide / Inject (祖先传后代)

    用于祖先组件向其任意深度的后代组件注入数据,不论组件层次有多深。这适用于全局或跨层级的状态管理,但应谨慎使用以避免过度依赖和状态难以追踪的问题。

  • Vuex 或 Pinia (全局状态管理)

    对于复杂应用,可以使用Vuex(Vue 2中常用)或Pinia(Vue 3推荐)作为状态管理工具。这些库提供了一个集中存储应用状态的地方,并允许组件从任何地方获取和改变状态。

  • Teleport (DOM节点的跨组件渲染)

    虽然Teleport主要用于将组件内容渲染到DOM树的不同部分,它本身不直接用于数据传递,但结合其他通信方式,可以实现特定场景下的数据流动。

  • Event Bus (非官方推荐)

    通过创建一个全局的事件总线(一个简单的Vue实例),可以在没有直接父子关系的组件间传递事件。但随着Vue 3 Composition API的出现,更推荐使用provide/inject或状态管理库。

  • Refs

    可以直接访问子组件的实例或DOM元素,从而操作子组件的数据或调用其方法。但这通常被视为最后的手段,因为它违反了Vue的单向数据流原则。

  • VueUse(本示例)

    通过VueUse提供的方法实现跨组件传递数据。

选择合适的数据传递方式对于维护可读性和可维护性的代码至关重要。简单数据交换推荐使用Props和Emit,全局状态管理考虑Vuex或Pinia,而复杂的组件结构可能需要借助Provide/Inject。

安装VueUse

pnpm i @vueuse/core

WARN  4 deprecated subdependencies found: @babel/plugin-proposal-class-properties@7.18.6, consolidate@0.15.1, stable@0.1.8, webpack-chain@6.5.1
Packages: +5
+++++
Progress: resolved 887, reused 881, downloaded 5, added 5, done
node_modules/.pnpm/vue-demi@0.14.7_vue@3.4.24/node_modules/vue-demi: Running postinstall script, done in 142ms

dependencies:
+ @vueuse/core 10.9.0

Done in 2.4s

测试组件

  1. father-component.vue
    <template>
      父亲节点 --
      <son-component></son-component>
    </template>
    <script setup lang="ts">
    import { ref } from "vue";
    // 引入子组件
    import SonComponent from "./son-component.vue";
    // 引入 provideLocal 方法
    import { provideLocal } from "@vueuse/core";
    // 需要传递给孙子组件的数据
    const fatherToGrandsonData = ref<{ data: string }>({
      data: "父亲传给孙子的数据",
    });
    // 将需要传递的数据保存到内存中
    provideLocal("FATHER-TO-GRANDSON-DATA", fatherToGrandsonData);
    </script>
    
  2. son-component.vue
    <template>儿子节点 -- <grandson-component></grandson-component></template>
    <script setup lang="ts">
    // 引入孙子组件
    import GrandsonComponent from "./grandson-component.vue";
    </script>
    
  3. grandson-component.vue
    <template>孙子组件 -- {{ fatherToGrandsonData?.data }}</template>
    <script setup lang="ts">
    // 引入 injectLocal
    import { injectLocal } from "@vueuse/core";
    // 从内存中获取父亲传递给孙子的数据
    const fatherToGrandsonData: { data: string } | undefined = injectLocal(
      "FATHER-TO-GRANDSON-DATA"
    );
    </script>
    

结果

20240424-145451.jpg

结语

Vue 3凭借其灵活多样的数据传递机制,让开发者能根据实际场景,选择最合适的通信策略,确保数据在组件间流畅、高效地流通,从而构建出既强大又可维护的应用。在设计组件间通信时,平衡好数据流向的清晰度与组件的独立性,是通往高质量Vue应用的关键。