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

前言

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

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

组件通信

父子组件通信

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

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

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

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

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

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

兄弟组件通信

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

    <!-- 父组件 -->
    <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>
<!-- 第一个兄弟组件 -->
    <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>
<!-- 第二个兄弟组件 -->
    <template>
      <div>
        <div>{{ message }}</div>
      </div>
    </template>

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

跨级组件通信

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

以下是一个示例:

祖先组件(AncestorComponent.vue)

<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)

<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)
<template>
  <div>
    <h3>{{ message }}</h3>
  </div>
</template>

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

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

总结

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

原文链接:https://juejin.cn/post/7324535599657500723 作者:为什么会变成这样呢

(0)
上一篇 2024年1月17日 上午10:37
下一篇 2024年1月17日 上午10:47

相关推荐

发表回复

登录后才能评论