Vue3组件通信方式详解

在 Vue 3 中,组件通信是构建复杂应用的关键部分。使用 <script setup> 语法糖可以让代码更加简洁和易读。以下是常见的组件通信方式,结合 <script setup> 语法糖进行讲解。


1. Props 和 Emit

这是 Vue 中最基础的父子组件通信方式。父组件通过 props 向子组件传递数据,子组件通过 emit 向父组件发送事件。

父组件

<template>
  <ChildComponent :message="parentMessage" @update-message="handleUpdateMessage" />
</template>

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

const parentMessage = ref('Hello from parent');

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

子组件

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="updateMessage">Update Message</button>
  </div>
</template>

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

const emit = defineEmits(['update-message']);

const updateMessage = () => {
  emit('update-message', 'New message from child');
};
</script>

2. Provide 和 Inject

provideinject允许祖先组件向其所有子孙组件传递数据,而不需要通过props层层传递。

祖先组件:

<template>
  <ChildComponent />
</template>

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

const message = ref('Hello from ancestor');

provide('message', message);
</script>

子孙组件:

<template>
  <div>
    <p>{{ injectedMessage }}</p>
  </div>
</template>

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

const injectedMessage = inject('message');
</script>

3.Refs 和 parent/children

通过ref可以直接访问子组件的实例,或者通过$parent$children访问父组件或子组件的实例

父组件

<template>
  <ChildComponent ref="child" />
  <button @click="callChildMethod">Call Child Method</button>
</template>

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

const child = ref(null);

const callChildMethod = () => {
  child.value.childMethod();
};
</script>

子组件

<template>
  <div>
    <p>Child Component</p>
  </div>
</template>

<script setup>
const childMethod = () => {
  console.log('Child method called');
};

defineExpose({
  childMethod
});
</script>

4.Event Bus

Event Bus 是一种全局事件通信方式,适用于非父子组件之间的通信。

Event Bus:

import { createApp } from 'vue';

export const eventBus = createApp({});

组件A

<template>
  <button @click="sendMessage">Send Message</button>
</template>

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

const sendMessage = () => {
  eventBus.emit('message', 'Hello from Component A');
};
</script>

组件B

<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

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

const message = ref('');

onMounted(() => {
  eventBus.on('message', (newMessage) => {
    message.value = newMessage;
  });
});
</script>

5.Vuex

Vuex 是 Vue 的官方状态管理库,适用于大型应用中的全局状态管理。

Store:

import { createStore } from 'vuex';

export default createStore({
  state: {
    message: 'Hello from Vuex'
  },
  mutations: {
    setMessage(state, newMessage) {
      state.message = newMessage;
    }
  },
  actions: {
    updateMessage({ commit }, newMessage) {
      commit('setMessage', newMessage);
    }
  }
});

组件A

<template>
  <button @click="updateMessage">Update Message</button>
</template>

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

const store = useStore();

const updateMessage = () => {
  store.dispatch('updateMessage', 'New message from Component A');
};
</script>

组件B

<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

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

const store = useStore();

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

6.Pinia

Pinia 是 Vue 3 官方推荐的状态管理库,比 Vuex 更轻量且易于使用。它适合管理全局状态,类似于 Vuex,但语法更简洁。

  • 安装npm install pinia

创建 Store

// stores/messageStore.js
import { defineStore } from 'pinia';

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

组件A

<template>
  <button @click="updateMessage">Update Message</button>
</template>

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

const messageStore = useMessageStore();

const updateMessage = () => {
  messageStore.updateMessage('New message from Component A');
};
</script>

组件B

<template>
  <div>
    <p>{{ messageStore.message }}</p>
  </div>
</template>

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

const messageStore = useMessageStore();
</script>

总结

以上六种组件通信方式涵盖了 Vue 3 中常见的场景。根据具体需求选择合适的通信方式,可以大大提高代码的可维护性和可读性。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容