文章

vue 组件通信

vue 组件通信

Vue 3组合式API通信方式:

1. 父子组件通信

通过 props 和 emit 实现:

  • props:父组件通过 props 向子组件传递数据。
  • emit:子组件可以通过 emit 向父组件发送事件和数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 父组件
<template>
  <ChildComponent :msg="parentMsg" @update="handleUpdate" />
</template>

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

const parentMsg = ref('Hello from Parent');
function handleUpdate(value) {
  console.log('Received from child:', value);
}
</script>

// 子组件
<template>
  <button @click="sendUpdate">Click to Update Parent</button>
</template>

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

const props = defineProps(['msg']);
const emit = defineEmits(['update']);

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

2. 兄弟组件通信

通过 provide 和 inject 共享数据:

Vue 3的 provide 和 inject 允许在祖先和后代组件之间共享数据,适合兄弟组件需要共享数据时在父级进行管理。

  • 父组件通过 provide 提供数据。
  • 子组件通过 inject 注入数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 父组件
<script setup>
import { provide, ref } from 'vue';

const sharedData = ref('Shared Data');
provide('sharedData', sharedData);
</script>

<template>
  <ChildComponentA />
  <ChildComponentB />
</template>

// 子组件 A
<script setup>
import { inject } from 'vue';

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

<template>
  <div>Data in A: {{ sharedData }}</div>
</template>

// 子组件 B
<script setup>
import { inject } from 'vue';

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

<template>
  <div>Data in B: {{ sharedData }}</div>
</template>

3. ref 和 reactive 的引用

在组合式API中,ref 和 reactive 可以将数据或对象设置为响应式,这些数据可以传递到不同的组件中来实现数据共享和状态管理。

1
2
3
4
5
6
7
8
9
10
11
12
// 使用ref共享单一变量
import { ref } from 'vue';

const sharedCount = ref(0);

// 使用reactive共享复杂对象
import { reactive } from 'vue';

const sharedState = reactive({
  count: 0,
  message: 'Hello World',
});

4. Event Bus 实现非父子组件通信

对于一些项目中不希望使用Vuex的场景,可以创建一个全局的 Event Bus,通过emit和on方式来实现。

1
2
3
4
import mitt from 'mitt';

const emitter = mitt();
export default emitter;

然后在不同的组件中使用:

1
2
3
4
5
6
7
8
9
10
11
// 组件 A
import emitter from './emitter';

emitter.emit('custom-event', payload);

// 组件 B
import emitter from './emitter';

emitter.on('custom-event', (payload) => {
  console.log('Received:', payload);
});

5. 使用 Vuex 或 Pinia 状态管理

对于较大型的项目,建议使用Vuex或Pinia来集中管理应用的状态。Pinia是Vue官方推荐的新的状态管理工具,特别适合Vue 3。

1
2
3
4
5
6
7
8
9
10
11
12
13
// store.js
import { defineStore } from 'pinia';

export const useStore = defineStore('main', {
  state: () => ({
    count: 0,
  }),
  actions: {
    increment() {
      this.count++;
    },
  },
});

在组件中使用:

1
2
3
4
import { useStore } from './store';

const store = useStore();
store.increment();

6. watch 和 watchEffect

当需要在不同的组件中监听数据变化时,可以使用watch 和 watchEffect。

  • watch:用于监听特定的数据变化。
  • watchEffect:用于监听任意响应式数据变化。
1
2
3
4
5
6
7
import { ref, watch } from 'vue';

const count = ref(0);

watch(count, (newValue, oldValue) => {
  console.log(`Count changed from ${oldValue} to ${newValue}`);
});
本文由作者按照 CC BY 4.0 进行授权