Vue3基础——组件通信
props传参
通常用于父组件和子组件的通信
- 在子组件中定义props,使用props
- 在父组件中传递参数
- 子组件向父组件传递需要使用回调的方式
子组件中定义props
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script setup lang="ts">
import {ref} from "vue";
// 定义props
defineProps(['value1', 'value2', 'getValue3']);
let value3 = ref('value3');
</script>
<template>
<div>{{value1}}</div>
<div>{{value2}}</div>
<!--调用回调,传递value3-->
<button @click="getValue3(value3)">向父组件传递value3</button>
</template>
在父组件中传递参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script setup lang="ts">
import {ref} from 'vue';
import Inner from "@/components/Inner.vue";
let value1 = ref('value1');
let value2 = ref('value2');
let value3 = ref('');
// 回调函数
function getValue3(value: string) {
value3.value = value;
}
</script>
<template>
<div>
<div>{{value3}}</div>
<!--传参-->
<Inner :value1="value1" :value2="value2" :getValue3="getValue3"></Inner>
</div>
</template>
自定义事件
主要用于父组件向子组件通信
- 在子组件中定义自定义事件,触发事件
- 在父组件中传递事件回调
在子组件中定义自定义事件,触发事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script setup lang="ts">
import {ref} from "vue";
let value = ref('value');
// 通过emit对象触发事件
const emit = defineEmits(['get-value']);
</script>
<template>
<!--传入触发的事件名和参数-->
<button @click="emit('get-value', value)">向父组件传递value</button>
</template>
在父组件中传递事件回调
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script setup lang="ts">
import {ref} from 'vue';
import Inner from "@/components/Inner.vue";
let value1 = ref('');
function getValue(value: string) {
value1.value = value;
}
</script>
<template>
<div>
<div>{{value1}}</div>
<!--自定义事件传入回调-->
<Inner @get-value="getValue"></Inner>
</div>
</template>
mitt消息总线
使用前安装mitt:npm i mitt
初始化消息总线emitter
1
2
3
import mitt from "mitt";
const emitter = mitt();
export default emitter;
emitter对象主要使用四个成员
all
:获取所有事件,返回事件和对应回调的mapon()
:绑定事件emit()
:触发事件off()
:注销事件
子组件接收value1,传递value2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script setup lang="ts">
import {ref} from "vue";
import emitter from "@/utils/emitter";
let value1 = ref('');
emitter.on('get-value1', (value) => {
if (typeof value === 'string') {
value1.value = value;
}
})
</script>
<template>
<div>{{value1}}</div>
<button @click="emitter.emit('get-value2', 'value2')">触发get-value2</button>
</template>
父组件接收value2,传递value1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script setup lang="ts">
import {ref} from 'vue';
import Inner from "@/components/Inner.vue";
import emitter from "@/utils/emitter";
let value2 = ref('');
emitter.on('get-value2', (value) => {
if (typeof value === 'string') {
value2.value = value;
}
})
</script>
<template>
<div>
<div>{{value2}}</div>
<button @click="emitter.emit('get-value1', 'value1')">触发get-value1</button>
<Inner></Inner>
</div>
</template>
在组件取消挂载时注销事件
1
2
3
onUnmounted(() => {
emitter.off('get-value1')
})
$attrs
用于父组件向子组件通信,在父组件传递参数时,若子组件未定义对应的props,则参数保存在$attrs
对象中
父组件传递参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script setup lang="ts">
import {ref} from 'vue';
import Inner from "@/components/Inner.vue";
let value1 = ref('value1')
let value2 = ref('value2');
</script>
<template>
<div>
<Inner :value1="value1" :value2="value2"></Inner>
</div>
</template>
子组件中未定义为props的参数会以键值对的形式保存到$attrs
对象中
1
2
3
4
5
6
7
8
9
10
11
12
13
<script setup lang="ts">
// value1定义为props,value2未定义,value2保存在$attrs对象中
defineProps(['value1']);
</script>
<template>
<!--
value1
{ "value2": "value2" }
-->
<div>{{value1}}</div>
<div>{{$attrs}}</div>
</template>
ref标签属性
ref标签属性可以获取组件的实例对象或HTML元素的DOM对象
- 子组件定义暴露的数据
- 父组件通过ref属性获取对象,获取暴露的数据
$refs
和$parent
$refs
:以键值对的形式存储所有使用ref属性的元素对象$parent
:当前组件的父组件对象
子组件中定义暴露的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script setup lang="ts">
import { ref } from 'vue'
const name = ref("张三")
const sayName = ()=>{
console.log("我叫 " + name.value)
}
// 使用defineExpose函数定义暴露的数据
defineExpose({name, sayName});
</script>
<template>
<div>{{name}}</div>
</template>
父组件通过ref属性获取子组件对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script setup lang="ts">
import {onMounted, ref} from 'vue';
import Inner from "@/components/Inner.vue";
let inner = ref();
// 在父组件挂载完成后使用子组件对象
onMounted(() => {
console.log(inner.value.name);
inner.value.sayName();
});
</script>
<template>
<div>
<Inner ref="inner"></Inner>
</div>
</template>
provide与inject
用于祖先组件向子组件提供数据
- 在祖先组件中使用provide提供数据
- 在子组件中使用inject获取数据
在祖先组件中提供数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script setup lang="ts">
import {provide, ref} from 'vue';
import Inner from "@/components/Inner.vue";
let value1 = ref('value1');
// 传入key和value
provide('key1', value1);
</script>
<template>
<div>
<Inner></Inner>
</div>
</template>
在子组件中获取数据
1
2
3
4
5
6
7
8
9
10
11
<script setup lang="ts">
import {inject} from 'vue';
// 第二个参数为默认值,可辅助ts类型推断
let value1 = inject('key1', 'defaultValue');
</script>
<template>
<div>{{value1}}</div>
</template>
本文由作者按照 CC BY 4.0 进行授权