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

前言

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 不失为一种更为合适的选择。

相关推荐
HEX9CF11 分钟前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
凌云行者23 分钟前
使用rust写一个Web服务器——单线程版本
服务器·前端·rust
华农第一蒟蒻39 分钟前
Java中JWT(JSON Web Token)的运用
java·前端·spring boot·json·token
积水成江40 分钟前
关于Generator,async 和 await的介绍
前端·javascript·vue.js
___Dream42 分钟前
【黑马软件测试三】web功能测试、抓包
前端·功能测试
金灰42 分钟前
CSS3练习--电商web
前端·css·css3
人生の三重奏1 小时前
前端——js补充
开发语言·前端·javascript
计算机学姐1 小时前
基于SpringBoot+Vue的高校运动会管理系统
java·vue.js·spring boot·后端·mysql·intellij-idea·mybatis
Tandy12356_1 小时前
js逆向——webpack实战案例(一)
前端·javascript·安全·webpack
TonyH20021 小时前
webpack 4 的 30 个步骤构建 react 开发环境
前端·css·react.js·webpack·postcss·打包