vue3组合式API之组件传值

vue3 组件传值

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-bindnowMsg是我们在子组件里定义的变量,把这个变量通过v-bind传递到子组件上,从而达到传递数据的效果

 <Children :msg="nowMsg"></Children>

这行代码中的Children是父组件通过这行代码定义的

import Children from './ChildrenVue.vue';

子组件上显示只需要用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中定义的属性名统一

效果如下:

在这里插入图片描述

4 案例:点菜

下面提供一个小案例,使用刚刚提到的知识,完成以下操作。

在这里插入图片描述

结构如下

在这里插入图片描述

4.1 答案解析

主页
<template>
    <div>
        <Menu :menus="menus" @onClickItem="onClickItem" :nowChoose="nowChooseMenu" />

        <Panel :nowChooseMenu="nowChooseMenu" :menus="menus" @onDeleteItem="onDeleteItem" />
    </div>
</template>
<script setup>
import Menu from './menuVue.vue'
import Panel from './panelVue.vue'
import { ref } from 'vue'
const nowChooseMenu = ref([])
const menus = ['宫保鸡丁', '辣子鸡丁']
const onClickItem = (item) => {
    console.log("当前选择的菜", item);
    nowChooseMenu.value.push(item)
}
const onDeleteItem = (index) => {
    nowChooseMenu.value.splice(index, 1)
}


</script>
菜单页面
<template>
    <div>
        <div>菜单</div>
        <div v-for="item in menus" :key="item">
            <span>{{ item }}</span>
            <button @click="onClickItem(item)" :disabled="nowChoose.indexOf(item) !== -1">点菜</button>
        </div>
    </div>
</template>

<script setup>
import { defineEmits, defineProps } from 'vue';
const emit = defineEmits(['onClickItem'])
const props = defineProps({
    menus: {
        type: Array,
        required: true,
    },
    nowChoose: {
        type: Array,
        required: true,
    }
});
const onClickItem = (item) => {
    emit('onClickItem', item)
}
</script>
已点菜单
<template>
    <div>
        <div>当前选择</div>
        <div v-for="(item, index) in nowChooseMenu" :key="item">
            <span>{{ item }}</span>
            <button @click="cancelItem(index)">取消选择</button>
        </div>
        <div v-show="menus.length === nowChooseMenu.length">已点完</div>
    </div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';

const props = defineProps({
    nowChooseMenu: {
        type: Array,
        required: true
    },
    menus: {
        type: Array,
        required: true,
    },
});

const emit = defineEmits(['onDeleteItem']);
const cancelItem = (index) => {
    emit('onDeleteItem', index)
}
</script>

可以使用v-model简化以上代码,使得父组件的功能更加单纯。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值