打破组件孤岛,带你了解组件通信

前言

vue.js 有两大特点,一个是数据驱动,另一个就是组件化,那么问题来了,什么叫做组件化,为什么要组件化? 所谓组件化,就是把页面拆分成多个组件,每个组件依赖的 CSS、JS、模板、图片等资源放在一起开发和维护。 因为组件是资源独立的,所以组件在系统内部可复用,组件和组件之间可以嵌套,如果项目比较复杂,可以极大简化代码量,并且对后期的需求变更和维护也更加友好。

但是Vue中各个组件,无论是定义全局的,还是局部的,各自都好似一座孤岛,无法"直接"访问到外部的如:data、computed、methods...等信息, 那就意味着变量、方法等等都要在一个组件中来完成。如果用Vue来构建一个项目,可想而知这是一件多么糟糕的事情。所以对于Vue各组件间如何实现相互通信显得尤为重要。以下便是一些组件通信的方法

组件通信

父子组件通信

父子组件通信是最基础的一种方式。父组件通过props向子组件传递数据,子组件通过$emit触发事件将数据传递回父组件。

  1. Props传递数据: 在父组件中使用props属性将数据传递给子组件,子组件通过props接收数据并使用。

    html 复制代码
    <!-- 父组件 -->
    <template>
      <child-component :message="parentMessage" />
    </template>
    
    <script>
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      data() {
        return {
          parentMessage: 'parent',
        };
      },
      components: {
        ChildComponent,
      },
    };
    </script>
    html 复制代码
    <!-- 子组件 -->
    <template>
      <div>{{ message }}</div>
    </template>
    
    <script>
    export default {
      props: ['message'],
    };
    </script>

其中父组件通过 props 向子组件传递了一个名为 parentMessage 的数据,子组件通过 message 接收并显示这个数据。

  1. $emit触发事件: 子组件通过$emit触发自定义事件,父组件通过v-on监听事件并处理数据。

    html 复制代码
    <!-- 子组件 -->
    <template>
      <button @click="sendMessage">Send Message</button>
    </template>
    
    <script>
    export default {
      methods: {
        sendMessage() {
          this.$emit('messageEvent', 'child');
        },
      },
    };
    </script>
    html 复制代码
    <!-- 父组件 -->
    <template>
      <child-component @messageEvent="handleMessage" />
    </template>
    
    <script>
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      methods: {
        handleMessage(message) {
          console.log(message); // 输出:child
        },
      },
      components: {
        ChildComponent,
      },
    };
    </script>

兄弟组件通信

兄弟组件之间的通信通过共同的父组件作为媒介来实现。

html 复制代码
    <!-- 父组件 -->
    <template>
      <div>
        <first-sibling :message="sharedMessage" @updateMessage="updateMessage" />
        <second-sibling :message="sharedMessage" />
      </div>
    </template>

    <script>
    import FirstSibling from './FirstSibling.vue';
    import SecondSibling from './SecondSibling.vue';

    export default {
      data() {
        return {
          sharedMessage: 'Hello from parent!',
        };
      },
      methods: {
        updateMessage(newMessage) {
          this.sharedMessage = newMessage;
        },
      },
      components: {
        FirstSibling,
        SecondSibling,
      },
    };
    </script>
html 复制代码
<!-- 第一个兄弟组件 -->
    <template>
      <div>
        <div>{{ message }}</div>
        <button @click="sendMessage">Send Message</button>
      </div>
    </template>

    <script>
    export default {
      props: ['message'],
      methods: {
        sendMessage() {
          this.$emit('updateMessage', 'Hello from first sibling!');
        },
      },
    };
    </script>
html 复制代码
<!-- 第二个兄弟组件 -->
    <template>
      <div>
        <div>{{ message }}</div>
      </div>
    </template>

    <script>
    export default {
      props: ['message'],
    };
    </script>

跨级组件通信

跨级组件通信通常发生在祖先组件和孙子组件之间,或者更远的组件关系。 Vue 提供了 provideinject 两个选项来实现这种跨级组件通信。通过 provide 在祖先组件中提供数据,然后在孙子组件中使用 inject 来注入这些数据。

以下是一个示例:

祖先组件(AncestorComponent.vue)

html 复制代码
<template>
  <div>
    <h1>{{ message }}</h1>
    <child-component />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  provide: {
    message: 'Hello from ancestor!',
  },
  components: {
    ChildComponent,
  },
};
</script>

子组件(ChildComponent.vue)

html 复制代码
<template>
  <div>
    <h2>{{ message }}</h2>
    <grandchild-component />
  </div>
</template>

<script>
import GrandchildComponent from './GrandchildComponent.vue';

export default {
  inject: ['message'],
  components: {
    GrandchildComponent,
  },
};
</script>
  1. 孙子组件(GrandchildComponent.vue)
html 复制代码
<template>
  <div>
    <h3>{{ message }}</h3>
  </div>
</template>

<script>
export default {
  inject: ['message'],
};
</script>

在这个例子中,祖先组件通过 provide 提供了一个名为 message 的数据。子组件通过 inject 注入了这个数据,并在模板中使用了它。孙子组件同样使用 inject 来获取祖先组件提供的 message 数据,实现了跨级组件通信。

总结

Vue提供了一套灵活的组件通信机制,可以很好地满足简单到中等复杂度的组件通信需求。然而,对于一些大型、复杂的应用,或者需要在多个组件之间共享状态和进行更强大的状态管理时,使用 Vuex或者pinia 不失为一种更为合适的选择。

相关推荐
加班是不可能的,除非双倍日工资6 分钟前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi39 分钟前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip1 小时前
vite和webpack打包结构控制
前端·javascript
excel1 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国2 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼2 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy2 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
草梅友仁2 小时前
草梅 Auth 1.4.0 发布与 ESLint v9 更新 | 2025 年第 33 周草梅周报
vue.js·github·nuxt.js
ZXT2 小时前
promise & async await总结
前端
Jerry说前后端2 小时前
RecyclerView 性能优化:从原理到实践的深度优化方案
android·前端·性能优化