关于vue3组件通讯

关于vue3组件通讯

The局外人 Lv Max

本篇文章采用<script setup>setup语法糖这种组合式API与TypeScript写法来讲述vue3到底有哪些常用且必须掌握的组件通讯的方式?前面讲述了vue2的组件通讯的方式。vue2与vue3类似,掌握vue2的基础上学习vue3也是十分简单。

props

父传子vue3中使用props也不例外,上代码!

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
35

//父组件
<template>
<div>
<Child :name="name" />
</div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import Child from "./views/Child/index.vue";
const name = ref("刘德华");
</script>

//子组件
<template>
<div>
{{ name }}
</div>
</template>

<script setup lang="ts">
const props = defineProps({
// 写法一
name: String,
// 写法二
name: {
type: String,
default: "",
},
});
</script>

<style scoped>
</style>

可以看出vue3中使用了一个defineProps宏函数,这个宏函数在vue3官方文档中也有相应的介绍,可用于接受父组件传递给子组件的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>
<div>
接收到子组件的数据为:{{name}}
<Child @name="receptionData" />
</div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import Child from "./views/Child/index.vue";
const name = ref("");
const receptionData = (names: string) => {
name.value = names;
};
</script>
//子组件
<template>
<div>
<button @click="sendData">点击传递数据</button>
</div>
</template>

<script setup lang="ts">
const emit = defineEmits(["name"]);
const sendData = () => {
emit("name","刘德华")
};
</script>

image1.pngimage2.png
可以看出,又出现了一个新的宏函数defineEmits这可以拿到相当于vue2组件实例上的$emit,用于触发自定义事件。

ref

ref可实现父组件调用子组件的方法,传递数据实现父向子传递数据

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

//父组件
<template>
<div>
<Child ref="child" />
<button @click="sendData">点击传递数据</button>
</div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import Child from "./views/Child/index.vue";
const child = ref();
const sendData=()=>{
child.value.receptionData("刘德华")
}
</script>

//子组件
<template>
<div></div>
</template>

<script setup lang="ts">
const receptionData = (name: string) => {
console.log("这是接收到父组件的数据", name);
};
// 暴露方法
defineExpose({
receptionData,
});
</script>

image3.png
const child = ref();ref="child"相同可拿到子组件实例,因为setup语法糖的缘故,父组件拿不到子组件的方法属性,必须通过defineExpose({})编译器宏函数暴露出去,注意一下!

v-model

v-model与vue2类似,可实现父子组件间数据传递

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
35
36
37

//父组件
<template>
<div>
{{ name }}
<Child :modelValue="name" @modelValue="modelValue" />
</div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import Child from "./views/Child/index.vue";
const name = ref("刘德华");
const modelValue = (inputVal: string) => {
name.value = inputVal;
};
</script>

//子组件
<template>
<div>
<input type="text" :value="modelValue" @input="changeInput" />
</div>
</template>

<script setup lang="ts">
const props = defineProps({
modelValue: {
type: String,
default: "",
}
});
const emit = defineEmits(["update:modelValue"]);
const changeInput = (e) => {
emit("modelValue", e.target.value);
};
</script>

image4.png
image5.png
vue3通过props与emit(自定义事件)实现父子组件相互传值,我通过v-model来简化代码,只需要做如下修改:

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

//父组件
<template>
<div>
{{ name }}
<Child v-model="name" />
</div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import Child from "./views/Child/index.vue";
const name = ref("刘德华");
</script>

//子组件
<template>
<div>
<input type="text" :value="modelValue" @input="changeInput" />
</div>
</template>

<script setup lang="ts">
const props = defineProps({
modelValue: {
type: String,
default: "",
}
});
const emit = defineEmits(["update:modelValue"]);
const changeInput = (e) => {
emit("update:modelValue", e.target.value);
};
</script>

由以上代码看出,在父组件中省略了:modelValue="name" @modelValue="modelValue"改为v-model="name",在子组件中emit("modelValue", e.target.value);改为emit("update:modelValue", e.target.value);效果一样。
注:如果使用v-model语法糖,你的props名必须为modelValue,自定义事件名为update:modelValue

provide/inject

provide与inject在vue3中同样是实现祖先与后代组件通讯

1
2
3
4
5
6
7
8
9
10
11
12
13
14

//父组件
<script setup>
import { provide } from "vue"
provide("name", "刘德华")
</script>

// 子组件
<script setup>
import { inject } from "vue"
const name = inject("name")
console.log(name) // 沐华
</script>

mitt

Vue3 中没有了 EventBus 跨组件通信,但是现在有了一个替代的方案 mitt.js,原理还是 EventBus
下载:npm i mitt 🤥😬
npm地址:mitt

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
35
36
37
38
39

//引入mitt插件:mitt一个方法,方法执行会返回bus对象
import mitt from 'mitt';
const Bus = mitt();
export default Bus;

//父组件
<template>
<div>
<Child />
<button @click="sendData">点击传递数据</button>
</div>
</template>

<script setup lang="ts">
import Bus from './mitt/index'
import Child from "./views/Child/index.vue";
const sendData=()=>{
Bus.emit('sendData','刘德华')
}
</script>

//子组件
<template>
<div>
这是接收父组件传来的数据,{{ names }}
</div>
</template>

<script setup lang="ts">
import Bus from '../../mitt/index'
import {onMounted,ref} from 'vue'
const names=ref("")
onMounted(() => {
Bus.on('sendData',(name:string)=>{
names.value=name
})
})
</script>

image6.png
image7.png
mit插件的用法,可以理解成消息的订阅发布,发布消息 Bus.emit('sendData','刘德华')订阅消息Bus.on('sendData',(name:string)=>{names.value=name})用法和全局事件总线相似。

写在最后

本文阐述了vue3的常用组件通讯,与vue2相比类似,还是希望大家先掌握vue2的组件通讯方式。如果你觉得上述有用,希望这篇文章,能帮助到你。

  • 标题: 关于vue3组件通讯
  • 作者: The局外人
  • 创建于 : 2023-09-03 21:10:14
  • 更新于 : 2023-09-04 16:12:19
  • 链接: https://dragon-xjy.gitee.io/2023/09/03/关于vue3组件通讯/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
 评论