vue3组合式API之组件传值
1.父传子使用defineProps
父组件是通过子组件定义的defineProps
来传递数据的,defineProps
是一个方法,可以接收数组,也能接收对象
1.1 完整代码
- 子组件
<template>
<div>儿子</div>
<div>父亲说:{{ props.msg }}</div>
</template>
<script setup>
// 先在子组件优先定义
import { defineProps } from 'vue';
//数组的接收方法
const props = defineProps(['msg'])
//对象的接收方法
// const props = defineProps({
// msg: {
// type: String,
// default: 'abcdf',
// required: true,
// },
// });
</script>
- 父组件
<template>
<div>父亲</div>
<div>------</div>
<Children :msg="nowMsg"></Children>
<!-- <Children /> -->
</template>
<script setup>
import Children from './ChildrenVue.vue';
const nowMsg = '好好学习'
</script>
1.2 逐步解析
首先需要导入defineProps
import { defineProps } from 'vue';
然后再子组件里面定义defineProps
const props = defineProps(['msg'])
注意这里的msg和父组件里的:msg相对应,这是由于在父组件中,是通过v-bind
指令将数据绑定到子组件的props上,:
是简写
v-bind
,nowMsg
是我们在子组件里定义的变量,把这个变量通过v-bind传递到子组件上,从而达到传递数据的效果
<Children :msg="nowMsg"></Children>
子组件上显示只需要用props.msg
就能显示父组件想要传递的信息了
如果是对象的传递方式可以只写定义的属性名
<div>父亲说:{{ msg }}</div>
const props = defineProps({
msg: {
type: String,
default: 'abcdf',
required: true,
},
});
2.子传父使用defineEmits
子组件通过defineEmits
方法,定义可以向父组件传递的事件,ndefineEmits
是一个方法,他能接受数组,数组之中每一个字符串,都代表一个可以向父组件emit
的事件
2.1 完整代码
根据前面的代码进行扩展
子组件
<template>
<div>儿子</div>
<div>父亲:{{ props.msg }}</div>
<button @click="handleToFather">传话给父亲</button>
</template>
<script setup>
// 先在子组件优先定义
import { defineProps, defineEmits } from "vue";
const props = defineProps(['msg'])
//自定义事件子传父
//define emits方法,接收一个数组,数字里的每一项,就是我们可以传给父组件的每一个自定义的事件
const emit = defineEmits(["toFather"]);
//调用emit方法,第一个参数是:事件名称,第二个参数是:传给外部的值
const handleToFather = () => {
emit("toFather", "我收到了");
};
</script>
父组件
<template>
<div>父亲</div>
<!-- <Children :msg="nowMsg"></Children> -->
<Children :msg="nowMsg" @toFather="handleFather" />
<div>孩子传给父亲的话:{{ fromChildMsg }}</div>
</template>
<script setup>
import Children from "./ChildrenVue.vue";
import { ref } from "vue";
const nowMsg = "好好学习";
const fromChildMsg = ref("");
const handleFather = (msg) => {
console.log(msg);
fromChildMsg.value = msg;
};
</script>
2.2 逐步解析
首先导入defineProps
import { defineProps } from "vue";
在子组件中,通过emit触发一个自定义事件,并将数据作为参数传递给父组件。在这里我们把自定义为toFather
const emit = defineEmits(["toFather"]);
本次案例中我们通过点击事件触发方法把数据发送到父组件去
//调用emit方法,第一个参数是:事件名称,第二个参数是:传给外部的值
const handleToFather = () => {
emit("toFather", "我收到了");
};
此时父组件需要通过@事件@toFather="handleFather"
来接收子组件的值
<Children :msg="nowMsg" @toFather="handleFather" />
注意这里@后面必须跟子组件自定义的名字相同
然后我们再写一个方法handleFather
来处理我们接收到的值
const handleFather = (msg) => {
console.log(msg);
fromChildMsg.value = msg;
};
由于fromChildMsg
使用了ref
所以我们需要.value
才能把获取到的msg传给fromChildMsg
输出到页面上
<div>孩子传给父亲的话:{{ fromChildMsg }}</div>
3.兄弟组件传值
按照规定来说组件之间只有单向传值,如果我们想让兄弟组件互相传值的话就必须借助父组件。
子组件1->父组件->子组件2
通过上述的流程达到兄弟组件传值的目的
本次样例我们把子组件1想要传递的信息通过父组件传到子组件2
3.1 完整代码
子组件1
<template>
<div class="wrapper">
<div>大儿子</div>
<button @click="handleToBrother">传话给兄弟</button>
</div>
</template>
<script setup>
// 先在子组件优先定义
import { defineEmits } from "vue";
const emit = defineEmits(["toBrother"]);
const handleToBrother = () => {
emit("toBrother", "该起床了");
};
</script>
子组件2
<template>
<div class="wrapper">
<div>2儿子</div>
<div>大儿子给2儿子的话:{{ brotherMsg }}</div>
</div>
</template>
<script setup>
// 先在子组件优先定义
import { defineProps } from "vue";
//对象的方式接收
const props = defineProps({
brotherMsg: {
type: String,
required: true,
},
});
</script>
父组件
<template>
<div>父亲</div>
<Children @toBrother="handleToBrother" />
<Children1 :brotherMsg="toBrotherMsg" />
</template>
<script setup>
import Children from "./ChildrenVue.vue";
import Children1 from "./ChildrenVue2.vue";
import { ref } from "vue";
const toBrotherMsg = ref("");
const handleToBrother = (msg) => {
toBrotherMsg.value = msg;
};
</script>
3.2 关键代码解析
首先在子组件2中需要预先定义它即将接收到的数据,这里我们使用对象的方式接收数据
//对象的方式接收
const props = defineProps({
brotherMsg: {
type: String,
required: true,
},
});
子组件1使用emit将需要发送的数据发给父组件
const handleToBrother = () => {
emit("toBrother", "该起床了");
};
父组件通过handleToBrother
接收到大儿子传递的信息,把数据存入toBrotherMsg
中
const handleToBrother = (msg) => {
toBrotherMsg.value = msg;
};
再通过父传子的方式,把数据传递给子组件2
<Children1 :brotherMsg="toBrotherMsg" />
注意:brotherMsg
需要和子组件2中定义的属性名统一