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

前言

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

相关推荐
Myli_ing14 分钟前
HTML的自动定义倒计时,这个配色存一下
前端·javascript·html
dr李四维32 分钟前
iOS构建版本以及Hbuilder打iOS的ipa包全流程
前端·笔记·ios·产品运营·产品经理·xcode
雯0609~1 小时前
网页F12:缓存的使用(设值、取值、删除)
前端·缓存
℘团子এ1 小时前
vue3中如何上传文件到腾讯云的桶(cosbrowser)
前端·javascript·腾讯云
学习前端的小z1 小时前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
星星会笑滴1 小时前
vue+node+Express+xlsx+emements-plus实现导入excel,并且将数据保存到数据库
vue.js·excel·express
彭世瑜1 小时前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund4041 小时前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish1 小时前
Token刷新机制
前端·javascript·vue.js·typescript·vue
小五Five1 小时前
TypeScript项目中Axios的封装
开发语言·前端·javascript