Vue3 的组件通讯→→→这一篇文章就够了(超级完整版)
  I7JaHrFMuDsU 2024年08月09日 33 0

在 Vue3 中,组件通讯是一个非常重要的概念,它决定了如何在父子组件之间、兄弟组件之间以及跨层级组件之间传递数据和事件。本文将详细介绍 Vue3 中的各种组件通讯方式,并结合具体示例,全面展示各种场景下的实现方法。所有示例将使用 Vue3 的 setup 语法糖来书写。

父子组件通讯是 Vue 中最常见的一种通讯方式。主要通过 props 和 emits 来实现。

1. 父组件传递数据给子组件(Props)

父组件通过 props 向子组件传递数据,这是最基本的通讯方式。

父组件(Parent.vue):

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

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

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

子组件(ChildComponent.vue):

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

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

const props = defineProps({
  message: {
    type: String,
    required: true,
  },
});
</script>
2. 子组件向父组件传递事件(Emits)

子组件通过 emits 向父组件传递事件。

父组件(Parent.vue):

<template>
  <div>
    <ChildComponent @update="handleUpdate" />
  </div>
</template>

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

const handleUpdate = (message) => {
  console.log('Received from child:', message);
};
</script>

子组件(ChildComponent.vue):

<template>
  <button @click="sendUpdate">Click Me</button>
</template>

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

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

const sendUpdate = () => {
  emit('update', 'Hello from Child!');
};
</script>

二、兄弟组件通讯

兄弟组件之间的通讯通常需要借助于父组件作为中介。

父组件(Parent.vue):

<template>
  <div>
    <SiblingOne @message="handleMessage" />
    <SiblingTwo :sharedMessage="sharedMessage" />
  </div>
</template>

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

const sharedMessage = ref('');

const handleMessage = (message) => {
  sharedMessage.value = message;
};
</script>

兄弟组件一(SiblingOne.vue):

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

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

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

const sendMessage = () => {
  emit('message', 'Hello from Sibling One!');
};
</script>

兄弟组件二(SiblingTwo.vue):

<template>
  <div>{{ sharedMessage }}</div>
</template>

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

const props = defineProps({
  sharedMessage: {
    type: String,
    default: '',
  },
});
</script>

三、跨层级组件通讯

跨层级组件通讯可以通过 Provide 和 Inject 来实现,这对于避免深层组件传递 props 和事件非常有用。

祖先组件(Ancestor.vue):

<template>
  <div>
    <DescendantComponent />
  </div>
</template>

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

const sharedState = ref('Hello from Ancestor!');
provide('sharedState', sharedState);
</script>

后代组件(DescendantComponent.vue):

<template>
  <div>{{ sharedState }}</div>
</template>

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

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

四、通过 ref 传递组件实例

有时我们需要在父组件中访问子组件的方法或属性,可以使用 ref 来获取子组件实例。

父组件(Parent.vue):

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

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

const child = ref(null);

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

子组件(ChildComponent.vue):

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

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

const someMethod = () => {
  console.log('Child method called!');
};

defineExpose({ someMethod });
</script>

五、使用 EventBus 实现全局事件通讯

在 Vue3 中,虽然官方不推荐使用 EventBus,但它仍然是一个简单的全局事件通讯方式。我们可以创建一个简单的 EventBus 实现:

EventBus.js:

import mitt from 'mitt';
const EventBus = mitt();
export default EventBus;

组件 A(ComponentA.vue):

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

<script setup>
import EventBus from './EventBus';

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

组件 B(ComponentB.vue):

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

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

const message = ref('');

onMounted(() => {
  EventBus.on('globalMessage', (msg) => {
    message.value = msg;
  });
});

onUnmounted(() => {
  EventBus.off('globalMessage');
});
</script>

六、使用 Vuex 实现全局状态管理

Vuex 是 Vue 官方提供的状态管理工具,可以帮助我们管理应用中的全局状态。下面是一个简单的示例。

安装 Vuex:

npm install vuex@next

Store(store.js):

import { createStore } from 'vuex';

export const store = createStore({
  state() {
    return {
      message: 'Hello from Vuex!'
    };
  },
  mutations: {
    updateMessage(state, newMessage) {
      state.message = newMessage;
    }
  },
  actions: {
    setMessage({ commit }, message) {
      commit('updateMessage', message);
    }
  },
  getters: {
    message: (state) => state.message
  }
});

主应用(main.js):

import { createApp } from 'vue';
import App from './App.vue';
import { store } from './store';

createApp(App)
  .use(store)
  .mount('#app');

组件 A(ComponentA.vue):

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

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

const store = useStore();

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

组件 B(ComponentB.vue):

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

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

const store = useStore();

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

七、使用 Pinia 实现全局状态管理

Pinia 是 Vue3 的新一代状态管理库,比 Vuex 更轻量且更易用。下面是一个简单的示例。

安装 Pinia:

npm install pinia

Store(store.js):

import { defineStore } from 'pinia';

export const useMainStore = defineStore('main', {
  state: () => ({
    message: 'Hello from Pinia!'
  }),
  actions: {
    setMessage(newMessage) {
      this.message = newMessage;
    }
  }
});

主应用(main.js):

import { createApp } from 'vue';
import App from './App.vue';
import { createPinia } from 'pinia';

const app = createApp(App);
const pinia = createPinia();

app.use(pinia);
app.mount('#app');

组件 A(ComponentA.vue):

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

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

const store = useMainStore();

const updateMessage = () => {
  store.setMessage('Hello from Component A!');
};
</

script>

组件 B(ComponentB.vue):

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

<script setup>
import { computed } from 'vue';
import { useMainStore } from './store';

const store = useMainStore();

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

结语

在 Vue3 中,组件通讯有多种方式可供选择,每种方式都有其特定的应用场景。通过合理使用 props、emits、Provide/Inject、ref、EventBus、Vuex 以及 Pinia 等技术,可以实现灵活高效的组件通讯。希望本文的内容和示例能帮助你更好地理解和应用 Vue3 的组件通讯技术。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2024年08月09日 0

暂无评论

推荐阅读
  I7JaHrFMuDsU   2024年08月09日   56   0   0 vue用户
I7JaHrFMuDsU