兄弟组件传值||共享状态、事件总线 (Event Bus) 和依赖 Vuex以及mitt

在 Vue 中,兄弟组件之间的通信有几种常见的方法,其中包括通过共享状态、使用事件总线 (Event Bus) 和依赖 Vuex 等状态管理库。下面将详细解释兄弟组件传参的几种方式。

1. 通过父组件中转

兄弟组件间通信最直接的方法是通过共同的父组件。父组件将数据通过 props 传递给子组件,子组件通过事件向父组件发送数据,然后父组件再将这些数据传递给另一个子组件。

示例:
<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildA @send-data="receiveData" />
    <ChildB :data="dataFromChildA" />
  </div>
</template>

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

const dataFromChildA = ref(null);

function receiveData(data) {
  dataFromChildA.value = data;
}
</script>
<!-- ChildA.vue -->
<template>
  <button @click="sendData">Send Data to Sibling</button>
</template>

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

const emit = defineEmits(['send-data']);

function sendData() {
  emit('send-data', 'Hello from ChildA');
}
</script>
<!-- ChildB.vue -->
<template>
  <div>Data from sibling: {{ data }}</div>
</template>

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

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

在这个例子中,ChildA 通过事件将数据发送给父组件,父组件再将这个数据通过 props 传递给 ChildB

2. 使用事件总线 (Event Bus)

事件总线是一种简单的发布-订阅模式,它允许你在组件间发送和接收事件。你可以在一个文件中创建一个 Vue 实例,并将其作为事件总线,在所有需要通信的组件中导入并使用它。

示例:
// bus.js
import { ref } from 'vue';

export const bus = ref(new Map());
<!-- ChildA.vue -->
<template>
  <button @click="sendMessage">Send Message</button>
</template>

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

function sendMessage() {
  bus.value.set('message', 'Hello from ChildA');
}
</script>
<!-- ChildB.vue -->
<template>
  <div>Message from sibling: {{ message }}</div>
</template>

<script setup>
import { ref, watch } from 'vue';
import { bus } from './bus';

const message = ref('');

watch(
  () => bus.value.get('message'),
  (newMessage) => {
    message.value = newMessage || '';
  }
);
</script>

在这个例子中,bus 是一个简单的事件总线,ChildA 通过 bus 发送信息,ChildB 通过 bus 监听信息的变化。

3. 使用 Vuex

如果你的应用程序较大且状态管理比较复杂,使用 Vuex 是推荐的方式。Vuex 是 Vue 的官方状态管理库,专门用于管理复杂的状态和组件间的通信。

示例:
// store.js
import { createStore } from 'vuex';

export const store = createStore({
  state() {
    return {
      message: ''
    };
  },
  mutations: {
    setMessage(state, message) {
      state.message = message;
    }
  }
});
<!-- ChildA.vue -->
<template>
  <button @click="sendMessage">Send Message via Vuex</button>
</template>

<script setup>
import { useStore } from 'vuex';

const store = useStore();

function sendMessage() {
  store.commit('setMessage', 'Hello from ChildA');
}
</script>
<!-- ChildB.vue -->
<template>
  <div>Message from sibling: {{ message }}</div>
</template>

<script setup>
import { computed } from 'vue';
import { useStore } from 'vuex';

const store = useStore();
const message = computed(() => store.state.message);
</script>

在这个例子中,ChildA 通过 Vuex 的 mutation 更新状态,ChildB 通过计算属性读取状态。

4. 使用 Provide/Inject API

尽管 provideinject 常用于祖孙组件之间的通信,它们也可以用于兄弟组件间的通信,通过在父组件中 provide 数据,然后在兄弟组件中 inject 数据来实现共享状态。

5.mitt

Mitt 是一个极其轻量级的事件总线库,适合在 Vue 3 应用中进行组件间通信。它实现了发布-订阅模式,可以让你在不同组件之间传递消息,而不需要复杂的状态管理工具如 Vuex。

安装 Mitt

你可以使用 npm 或 yarn 安装 Mitt:

npm install mitt
# or
yarn add mitt
使用 Mitt 进行组件通信
1. 创建一个事件总线

首先,你需要创建一个 Mitt 实例。通常,我们会在一个单独的文件中创建这个实例,并在需要的地方导入。

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

const emitter = mitt();

export default emitter;
2. 在组件中使用 Mitt

假设你有两个兄弟组件 ChildAChildB,它们需要相互通信。你可以在 ChildA 中发布事件,并在 ChildB 中监听该事件。

<!-- ChildA.vue -->
<template>
  <button @click="sendMessage">Send Message</button>
</template>

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

function sendMessage() {
  emitter.emit('message', 'Hello from ChildA');
}
</script>
<!-- ChildB.vue -->
<template>
  <div>Message from sibling: {{ message }}</div>
</template>

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

const message = ref('');

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

onMounted(() => {
  emitter.on('message', handleMessage);
});

onUnmounted(() => {
  emitter.off('message', handleMessage);
});
</script>
3. 事件的发布和订阅
  • 发布事件:通过 emitter.emit(eventName, payload) 发布事件。eventName 是事件的名称,payload 是传递的数据。

  • 监听事件:通过 emitter.on(eventName, handler) 监听事件。handler 是当事件触发时的回调函数。

  • 取消监听:当组件销毁时,可以使用 emitter.off(eventName, handler) 来取消事件的监听,防止内存泄漏。

4. 全局注册 Mitt (可选)

如果你的应用程序中有很多组件需要使用 Mitt,你可以在 Vue 应用的全局上下文中注册 Mitt 实例。

// main.js
import { createApp } from 'vue';
import App from './App.vue';
import mitt from 'mitt';

const app = createApp(App);
app.config.globalProperties.$emitter = mitt();
app.mount('#app');

在这种情况下,你可以在任何组件中通过 this.$emitter 访问 Mitt 实例:

<script setup>
const { $emitter } = getCurrentInstance().appContext.config.globalProperties;
$emitter.emit('message', 'Hello globally');
</script>

总结

兄弟组件之间传递参数的方式有很多,选择适合自己应用的方式非常重要。对于简单的应用,可以使用 props 和事件。对于中等复杂的应用,事件总线是一个有效的选择。而对于大型应用,Vuex 是推荐的解决方案。

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3中兄弟组件传值有多种方法,其中两种常用的方法如下: 1.使用事件总线Event Bus)进行传值,具体步骤如下: 在父组件中创建一个事件总线实例,并在需要传值的地方触发事件,将数据作为参数传递给事件;在子组件中监听该事件,并在回调函数中获取传递的数据。示例代码如下: // 父组件 <template> <div> <h1>我是父组件</h1> <button @click="sendMsg">发送消息给子组件</button> </div> </template> <script> import { ref } from 'vue' import mitt from 'mitt' export default { setup() { const emitter = mitt() const msg = ref('父组件的消息') const sendMsg = () => { emitter.emit('getMsg', msg.value) } return { emitter, sendMsg } } } </script> // 子组件 <template> <div> <h1>我是子组件</h1> <p>{{ msg }}</p> </div> </template> <script> import { ref, onMounted } from 'vue' import mitt from 'mitt' export default { setup() { const emitter = mitt() const msg = ref('') onMounted(() => { emitter.on('getMsg', (data) => { msg.value = data }) }) return { emitter, msg } } } </script> 2.使用插件mitt进行传值,具体步骤如下: 在父组件和子组件中都引入mitt插件,并在父组件中创建一个mitt实例,然后在需要传值的地方调用emit方法,将数据作为参数传递给子组件;在子组件中通过props接收父组件传递的数据。示例代码如下: // 父组件 <template> <div> <h1>我是父组件</h1> <button @click="sendMsg">发送消息给子组件</button> </div> </template> <script> import { ref } from 'vue' import mitt from 'mitt' export default { setup() { const emitter = mitt() const msg = ref('父组件的消息') const sendMsg = () => { emitter.emit('getMsg', msg.value) } return { emitter, sendMsg } } } </script> // 子组件 <template> <div> <h1>我是子组件</h1> <p>{{ msg }}</p> </div> </template> <script> import { ref, onMounted, reactive } from 'vue' import mitt from 'mitt' export default { props: { msg: { type: String, default: '' } }, setup(props) { const emitter = mitt() onMounted(() => { emitter.on('getMsg', (data) => { props.msg = data }) }) return { emitter } } } </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值