组件通信props方式
组件通信的概念
简单来说,在vue中,组件就是来构建一个一个的页面的。所谓的组件通信就是各个组件的连接扣;
父子通信基石
这是最基础、最高频的通信方式
1.父传子:Props
预置代码
VUE
##子组件
<template>
<div class="box">
<h3>子组件</h3>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped>
.box {
background-color: #88ccee;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
</style>
vue
##父组件
<template>
<div class="box">
<h3>父组件</h3>
<Child />
</div>
</template>
<script setup lang="ts">
import Child from './Child.vue'
</script>
<style scoped>
.box {
background-color: #999;
padding: 20px;
border-radius: 10px;
}
</style>
- 现在我们向父组件写点数据,例如父亲有100w存款
vue
import { ref } from 'vue';
const Money = ref('存折100W');

- 现在父组件要把100w传给子组件
vue
//父组件
<Child :money="Money" />
vue
//子组件
<template>
<div class="box">
<h3>子组件</h3>
<h3>父给子的:{{ money }}</h3>
</div>
</template>
<script setup lang="ts">
defineProps(['money'])
</script>

注意
这里还老生常谈的几个注意事项:
-
在HTML模板中,驼峰式命名会被props自动转换为短横线形式,例如initCount会被转为init-count;
-
如果props被解构,被解构出来的变量会失去响应式,可以使用toRefs来为其变为响应式;
2. 子传父
(一)使用回调函数的方式
- 首先父亲先定义一个方法,这个方法用于子组件向他传递东西
vue
function getToy(value: string) {
console.log(value);
}
- 然后将这个函数传递给子组件
vue
<Child :money="Money" :sendToy="getToy" />
- 然后我们给子组件写点数据,并生成也给按钮,按钮点击之后向父组件发送数据
vue
<script setup lang="ts">
defineProps(['money', "sendToy"])
import { ref } from 'vue';
let toy = ref("迪迦奥特曼")
</script>
<template>
<div class="box">
<h3>子组件</h3>
<h4>玩具:{{ toy }}</h4>
<h3>父给子的:{{ money }}</h3>
<button @click="sendToy(toy)">把玩具给父亲</button>
</div>
</template>
- 之后我们将数据呈现到父组件上面去
vue
<template>
<div class="box">
<h3>父组件</h3>
<h4>{{ Money }}</h4>
<h4 v-show="ChildToy">子父的玩具:{{ ChildToy }}</h4>
<Child :money="Money" :sendToy="getToy" />
</div>
</template>
<script setup lang="ts">
import Child from './Child.vue'
import { ref } from 'vue';
let Money = ref('存折100W');
let ChildToy = ref('');
function getToy(value: string) {
ChildToy.value = value;
}
</script>

(二)使用Emits的方式、
子组件通过 defineEmits 声明事件,并在适当时机触发,父组件监听该事件。直接给代码解释
vue
<template>
<div class="box">
<h3>子组件</h3>
<h4>玩具:{{ toy }}</h4>
<h3>父给子的:{{ money }}</h3>
<button @click="handleClick">把玩具给父亲</button>
</div>
</template>
<script setup lang="ts">
defineProps(['money'])
import { ref } from 'vue';
let toy = ref("迪迦奥特曼")
const emit = defineEmits(['toy'])
function handleClick() {
emit('toy', toy)
}
</script>
<style scoped>
.box {
background-color: #88ccee;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
</style>
vue
<template>
<div class="box">
<h3>父组件</h3>
<h4>{{ Money }}</h4>
<h4 v-show="ChildToy">子给父的玩具: {{ ChildToy }}</h4>
<Child :money="Money" @toy="updateToy" />
</div>
</template>
<script setup lang="ts">
import Child from './Child.vue'
import { ref } from 'vue';
let Money = ref('存折100W');
const ChildToy = ref('')
function updateToy(val: string) {
ChildToy.value = val
}
</script>
<style scoped>
.box {
background-color: #999;
padding: 20px;
border-radius: 10px;
}
</style>

上面的代码简单解释一下:
- defineEmits是用来声明你想要触发什么样的事件;
- emit有两个参数,第一个参数是你想触发什么样的事件,第二个是事件携带的参数;
- 之后在父组件定义一个处理函数,然后监听子组件的事件;
- 上面还需要引入一个event知识点,我们发现再子组件中,是通过event知识点,我们发现再子组件中,是通过event知识点,我们发现再子组件中,是通过emit来注册事件的,然后将数据作为参数传入进行,那么在父组件中是通过event接受的;在原生DOM中,event接受的;在原生DOM中,event接受的;在原生DOM中,event是该事件的事件对象;如果是在自定义事件 (比如子组件
emit触发的事件),$event指向的是子组件emit时传递的第一个参数 (如果传递了多个参数,$event是一个数组,包含所有参数)。
总结
- props是使用频率最高的,它可以实现父传子,子传父;
- 如果是父传子,属性值不是函数,如果是子传父的话,属性值就是函数了;
- 当组件有多层嵌套的时候,千万不要使用Props来传递,虽然这样可以,但是非常痛苦;
- Vue是单项数据流,父组件通过props向子组件传递数据,数据是向下流动的;子组件是向父组件通知变化(事件向上冒泡);设计这样的数据流动的话,便于调试和维护;永远不要在子组件中直接修改父组件传递过来的
props。