Vue 2 和 Vue 3 组件通信详解

Vue 2 和 Vue 3 组件通信详解

组件通信是前端开发中的重要部分,尤其在使用 Vue.js 构建复杂应用时,组件之间的数据传递和事件处理显得尤为重要。本文将详细介绍在 Vue 2 和 Vue 3 中如何实现父传子、子传父,以及兄弟组件之间的通信,同时在 Vue 3 中还会展示使用插件来实现兄弟组件之间的通信。

一、父传子通信

1. Vue 2 的实现

在 Vue 2 中,父组件通过 props 向子组件传递数据。props 是一种单向数据流,数据只能从父组件流向子组件。

父组件:Parent.vue

<template>
  <div>
    <Child :message="parentMessage" />
  </div>
</template>

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

export default {
  components: { Child },
  data() {
    return {
      parentMessage: 'Hello from Parent'
    };
  }
};
</script>

子组件:Child.vue

<template>
  <div>
    子组件接收到的消息: {{ message }}
  </div>
</template>

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

2. Vue 3 的实现

在 Vue 3 中,父传子依然通过 props 实现,但可以使用 setup 语法糖进行处理,代码更简洁。

父组件:Parent.vue

<template>
  <div>
    <Child :message="parentMessage" />
  </div>
</template>

<script setup>
import { ref } from 'vue';
import Child from './Child.vue';

const parentMessage = ref('Hello from Parent');
</script>

子组件:Child.vue

<template>
  <div>
    子组件接收到的消息: {{ message }}
  </div>
</template>

<script setup>
import { defineProps } from 'vue';

const props = defineProps({
  message: String
});
</script>

二、子传父通信

1. Vue 2 的实现

在 Vue 2 中,子组件可以通过 $emit 触发事件来将数据传递给父组件。

父组件:Parent.vue

<template>
  <div>
    <Child @update-message="handleUpdateMessage" />
    <p>从子组件接收到的消息: {{ parentMessage }}</p>
  </div>
</template>

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

export default {
  components: { Child },
  data() {
    return {
      parentMessage: ''
    };
  },
  methods: {
    handleUpdateMessage(newMessage) {
      this.parentMessage = newMessage;
    }
  }
};
</script>

子组件:Child.vue

<template>
  <div>
    <button @click="sendMessage">发送消息给父组件</button>
  </div>
</template>

<script>
export default {
  methods: {
    sendMessage() {
      this.$emit('update-message', 'Hello from Child');
    }
  }
};
</script>

2. Vue 3 的实现

在 Vue 3 中,子组件依然可以通过 emit 来触发事件,将数据传递给父组件。

父组件:Parent.vue

<template>
  <div>
    <Child @updateMessage="handleUpdateMessage" />
    <p>从子组件接收到的消息: {{ parentMessage }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import Child from './Child.vue';

const parentMessage = ref('');

function handleUpdateMessage(newMessage) {
  parentMessage.value = newMessage;
}
</script>

子组件:Child.vue

<template>
  <div>
    <button @click="sendMessage">发送消息给父组件</button>
  </div>
</template>

<script setup>
import { defineEmits } from 'vue';

const emit = defineEmits(['updateMessage']);

function sendMessage() {
  emit('updateMessage', 'Hello from Child');
}
</script>

三、兄弟组件通信

兄弟组件之间的通信通常需要通过一个共同的父组件,或者使用事件总线、状态管理工具来共享数据。

1. Vue 2 的实现

在 Vue 2 中,常见的做法是使用一个事件总线(Event Bus)或 Vuex 来进行兄弟组件之间的通信。这里我们用一个简单的事件总线来演示。

事件总线:bus.js

import Vue from 'vue';
export const EventBus = new Vue();

兄弟组件A:SiblingA.vue

<template>
  <div>
    <button @click="sendMessage">发送消息到兄弟组件B</button>
  </div>
</template>

<script>
import { EventBus } from './bus.js';

export default {
  methods: {
    sendMessage() {
      EventBus.$emit('message-from-a', 'Hello from Sibling A');
    }
  }
};
</script>

兄弟组件B:SiblingB.vue

<template>
  <div>
    <p>从兄弟组件A接收到的消息: {{ message }}</p>
  </div>
</template>

<script>
import { EventBus } from './bus.js';

export default {
  data() {
    return {
      message: ''
    };
  },
  mounted() {
    EventBus.$on('message-from-a', (msg) => {
      this.message = msg;
    });
  }
};
</script>

2. Vue 3 的实现

在 Vue 3 中,我们可以使用 provideinject 进行兄弟组件之间的通信,也可以使用第三方状态管理库 Pinia

使用 provideinject

父组件:Parent.vue

<template>
  <div>
    <SiblingA />
    <SiblingB />
  </div>
</template>

<script setup>
import { ref, provide } from 'vue';
import SiblingA from './SiblingA.vue';
import SiblingB from './SiblingB.vue';

const sharedMessage = ref('Initial Message');
provide('sharedMessage', sharedMessage);
</script>

兄弟组件A:SiblingA.vue

<template>
  <div>
    <button @click="updateMessage">更新消息</button>
  </div>
</template>

<script setup>
import { inject } from 'vue';

const sharedMessage = inject('sharedMessage');

function updateMessage() {
  sharedMessage.value = 'Message updated by Sibling A';
}
</script>

兄弟组件B:SiblingB.vue

<template>
  <div>
    <p>从Sibling A更新的消息: {{ sharedMessage }}</p>
  </div>
</template>

<script setup>
import { inject } from 'vue';

const sharedMessage = inject('sharedMessage');
</script>

使用 Pinia 进行兄弟组件通信

Pinia 是 Vue 3 的状态管理库,使用它可以很方便地在兄弟组件之间共享状态。

安装 Pinia

npm install pinia

创建 Pinia Store:store.js

import { defineStore } from 'pinia';

export const useMessageStore = defineStore('message', {
  state: () => ({
    message: 'Initial Message'
  }),
  actions: {
    updateMessage(newMessage) {
      this.message = newMessage;
    }
  }
});

父组件:Parent.vue

<template>
  <div>
    <SiblingA />
    <SiblingB />
  </div>
</template>

<script setup>
import { createPinia } from 'pinia';
import { useMessageStore } from './store';
import SiblingA from './SiblingA.vue';
import SiblingB from './SiblingB.vue';

const pinia = createPinia();
</script>

兄弟组件A:SiblingA.vue

<template>
  <div>
    <button @click="updateMessage">更新消息</button>
  </div>
</template>

<script setup>
import { useMessageStore } from './store';

const store = useMessageStore();

function updateMessage() {
  store.updateMessage('Message updated by Sibling A');
}
</script>

兄弟组件B:SiblingB.vue

<template>
  <div>
    <p>从Sibling A更新的消息: {{ store.message }}</p>
  </div>
</template>

<script setup>
import { useMessageStore } from './store';

const store = useMessageStore();
</script>

下面是一个使用 mitt 在 Vue 3 中实现兄弟组件之间通信的示例。

安装 mitt

首先,需要安装 mitt

npm install mitt

创建事件总线

在项目中创建一个事件总线文件,比如 eventBus.js

// eventBus.js
import mitt from 'mitt';

const eventBus = mitt();

export default eventBus;

兄弟组件通信示例

兄弟组件A:SiblingA.vue

<template>
  <div>
    <button @click="sendMessage">发送消息到兄弟组件B</button>
  </div>
</template>

<script setup>
import eventBus from './eventBus.js';

function sendMessage() {
  eventBus.emit('messageFromA', 'Hello from Sibling A');
}
</script>

兄弟组件B:SiblingB.vue

<template>
  <div>
    <p>从兄弟组件A接收到的消息: {{ message }}</p>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import eventBus from './eventBus.js';

const message = ref('');

function handleMessage(msg) {
  message.value = msg;
}

onMounted(() => {
  eventBus.on('messageFromA', handleMessage);
});

onUnmounted(() => {
  eventBus.off('messageFromA', handleMessage);
});
</script>

父组件:Parent.vue

将兄弟组件 A 和 B 放在一个父组件中:

<template>
  <div>
    <SiblingA />
    <SiblingB />
  </div>
</template>

<script setup>
import SiblingA from './SiblingA.vue';
import SiblingB from './SiblingB.vue';
</script>

解释

  1. 事件总线 (mitt): mitt 是一个轻量级的事件触发器,提供了 emiton 等方法,帮助组件之间进行消息传递。

  2. 兄弟组件A (SiblingA): 通过 eventBus.emit('messageFromA', 'Hello from Sibling A'); 发送消息。

  3. 兄弟组件B (SiblingB): 使用 eventBus.on('messageFromA', handleMessage); 监听消息,并在组件卸载时通过 eventBus.off 取消监听,避免内存泄漏。

通过这种方式,兄弟组件之间可以轻松实现通信,不需要通过父组件进行中转。这种模式在 Vue 3 中使用 mitt 特别简单有效,尤其适用于需要在多个组件间共享事件的场景。

结语

在 Vue 开发中,组件之间的通信是构建复杂应用的基础。无论是父传子、子传父,还是兄弟组件之间的通信,Vue 2 和 Vue 3 都提供了多种方式来实现。通过合理使用这些通信方式,开发者可以更高效地管理组件间的数据传递和事件处理。在 Vue 3 中,随着 Composition API 的引入以及状态管理工具如 Pinia 的出现,组件通信变得更加灵活和易于维护。

希望这篇文章能帮助你更好地理解 Vue 2 和 Vue 3 中的组件通信,并在实际项目中灵活运用这些技巧。

  • 18
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值