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

前言

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

相关推荐
桂月二二25 分钟前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
沈梦研1 小时前
【Vscode】Vscode不能执行vue脚本的原因及解决方法
ide·vue.js·vscode
hunter2062062 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb2 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角2 小时前
CSS 颜色
前端·css
轻口味2 小时前
Vue.js 组件之间的通信模式
vue.js
浪浪山小白兔3 小时前
HTML5 新表单属性详解
前端·html·html5
lee5763 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579653 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
limit for me4 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架