vue3中的组件通信方式

文章类型:Vue

发布者:hp

发布时间:2024-11-22

一:概述

在进行vue3项目开发时候,我们不可避免会涉及数据交互,比如父子组件通信,兄弟组件通信,后代组件通信,那么怎么来实现对应的功能呢,

二:方式

1:Props(父组件像子组件传递数据)

父组件

<template>
  <div>
    <ChildComponent :childData="parentData" />
  </div>
</template>

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

const parentData = ref('这是来自父组件的数据');
</script>

子组件

<template>
  <div>{{ childData }}</div>
</template>

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

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

2:Custom Events(子组件向父组件传递数据)

父组件

<template>
  <div>
    <ChildComponent @update:parentData="handleParentDataUpdate" />
    <p>父组件接收到的数据:{{ parentReceivedData }}</p>
  </div>
</template>

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

const parentReceivedData = ref('');

function handleParentDataUpdate(data) {
  parentReceivedData.value = data;
}
</script>

子组件

<template>
  <button @click="notifyParent">通知父组件</button>
</template>

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

const emits = defineEmits(['update:parentData']);

function notifyParent() {
  emits('update:parentData', '这是来自子组件的数据');
}
</script>

3:Provide / Inject(跨组件传递数据)

祖先组件

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

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

provide('ancestorData', '这是来自祖先组件的数据');
</script>

后代组件

<template>
  <div>{{ ancestorData }}</div>
</template>

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

const ancestorData = inject('ancestorData', '默认值');
</script>

4:Refs(父组件访问子组件实例)

父组件

<template>
  <div>
    <ChildComponent ref="childRef" />
    <button @click="accessChildMethod">调用子组件方法</button>
  </div>
</template>

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

const childRef = ref(null);

function accessChildMethod() {
  if (childRef.value) {
    childRef.value.childMethod();
  }
}
</script>

子组件

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

function childMethod() {
  console.log('子组件方法被调用');
}

defineExpose({
  childMethod
});
</script>

5:Vuex/Pinia(状态管理),用于集中管理所有组件的共享状态。它们提供了全局状态存储和跨组件访问状态的能力,可以有效地管理这些状态,并保持应用的可维护性和可扩展性

6:v-mode进行父子组件双向数据绑定

父组件

<template>
  <div>
    <ChildComponent v-model:childData="parentData" />
    <p>父组件的数据:{{ parentData }}</p>
  </div>
</template>

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

const parentData = ref('初始数据');
</script>

子组件

<template>
  <div>
    <input v-model="localData" @input="updateValue" />
  </div>
</template>

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

const props = defineProps({
  modelValue: String
});

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

const localData = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
});

function updateValue(event) {
  // 这里通常不需要手动调用,因为v-model已经处理了
  // 但如果需要基于输入值做进一步处理后再更新,可以在这里添加逻辑
}
</script>

7:使用三方库mitt或EventBus进行跨组件通信,(轻量级事件发射、订阅库)

npm install mitt
// eventBus.js
import mitt from 'mitt';
const emitter = mitt();
export default emitter;

//组件使用
// 发送事件的组件
<script setup>
import emitter from './eventBus';

function sendMessage() {
  emitter.emit('message', 'Hello from anywhere!');
}
</script>

// 监听事件的组件
<script setup>
import { onMounted, onUnmounted } from 'vue';
import emitter from './eventBus';

onMounted(() => {
  emitter.on('message', (msg) => {
    console.log(msg); // 输出: Hello from anywhere!
  });
});

onUnmounted(() => {
  emitter.off('message'); // 清理事件监听,避免内存泄漏
});
</script>

三:总结

1:父传子采用props,子传父defineEmits