0%

Vue3 组件通信方式

面试题经常会问到 vue3 组件间的通信方式,下文列举了七种常见的通信方式。

  • props (父传子)
  • emit (子传父)
  • v-model
  • refs
  • provide/inject
  • eventBus
  • Vuex4/pinia(vuex5)

1. Props 方式

父组件以数据绑定的形式声明要传递的数据,子组件通过defineProperty()方法创建 props 对象,即可拿到父组件传来的数据。
父组件的 template 中:

1
2
<!-- list是我们要传递的数据 -->
<child-components :list="list"></child-components>

子组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<ul>
<li v-for="i in props.list" :key="i">{{ i }}</li>
</ul>
</template>
<script setup>
import { defineProps } from 'vue'
const props = defineProps({
list: {
type: Array,
default: () => [],
},
})
</script>

2. emit 方式

emit 方式也是 Vue 中最常见的组件通信方式,该方式用于子传父
父组件的 template 中:

1
2
3
4
5
6
7
8
9
<!-- add是子组件要传递的动作,handleAdd是监听到之后执行的事件 -->
<child-components @add="handleAdd"></child-components>
<script>
const list = ref([1,2,3])
const handleAdd = value => {
list.value.push(value)
}
</script>

子组件中:

1
2
const emits = defineEmits(["add"]);
emits("add", 1);

3. v-model 方式

v-model 不能严格成为数据的传递方式,其实只是减少了代码量。

1
2
3
<ChildComponent v-model:list="list" />
// 等价于
<ChildComponent :list="pageTitle" @update:list="list = $event" />

子组件需要 emit 一个叫 update:xxx 的事件,再把需要更新的响应式数据传给 emit 方法的第二个参数即可,如:

1
2
const emits = defineEmits(["update:list"]);
emits("update:list", arr);

4、Refs

有时候想访问 r e f s 绑 定 的 组 件 的 属 性 或 者 方 法 , 我 们 会 使 用 refs 绑定的组件的属性或者方法,我们会使用 refs 绑定的组件的属性或者方法,我们会使用 refs。但是 Vue3 不同于 Vue2,在 Vue3 的 setup 中我们是无法访问到 this 的,所以我们需要借助一个方法,那就是 getCurrentInstance,该方法返回了当前的实例对象。
父组件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<div>
<Child ref="child"></Child>
<button @click="show">Show Child Message</button>
</div>
</template>
<script setup>
import { getCurrentInstance } from '@vue/runtime-core';
import Child from './Child.vue';
const currentInstance = getCurrentInstance()
function show() {
currentInstance.$refs.child.alertMessage()
}
</script>

子组件代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div>
<h1>{{ message }}</h1>
</div>
</template>
<script setup>
import { ref } from '@vue/reactivity';
let message = ref('我是子元素').value
const alertMessage = function () {
alert(message)
}
defineExpose({
message,
alertMessage
})
</script>

注意 ⚠️,通过<script setup>语法糖的写法,其组件是默认关闭的,也就是说如果是通过$refs或者$parents 来访问子组件中定义的值是拿不到的,必须通过defineExpose向外暴露你想获取的值才行。

5. provide/inject

provide/inject 是 Vue 中提供的一对 API。无论层级多深,API 都可以实现父组件到子孙组件的数据传递。

1
2
3
4
5
// 父组件中
provide("list", list.value);

// 子组件中
const list = inject("list");

6. eventBus

Vue 3 中移除了 eventBus,但可以借助第三方工具来完成。Vue 官方推荐使用 mitt 或 tiny-emitter。
Vue3 mitt

7. Vuex/Pinia

VuexPinia 是 Vue 3 中的状态管理工具,使用这两个工具可以轻松实现组件通信。

赏包辣条吃吧