揭秘:父子组件之间的传递

基础知识

组件与组件之间有三大方面的知识点:

  • 子组件通过props = defineProps({})接收父组件传递到参数和方法;
  • 子组件可以通过定义 emit 事件,向父组件发送事件;
  • 父组件调用子组件通过defineExpose 导出的方法

一、props==>接收父组件的参数和方法

子组件通过props = defineProps({})可以接收父组件传来的变量参数和方法;

示例如下:

const props = defineProps({page: number, //v-model:page vue3中的v-model新特性,支持多个v-model的数据绑定total:number, //普通传递参数queryParams: {   // 初始表单数据type: Object,default: () => ({processor: '',remark: ''})},getList: {  //父组件方法type: Function,default: () => {}});

父组件传递的方法和参数 ,具体示例如下:假设子组件为TabComponent

<TabComponent v-model:page="pageValue" ref="LegShippingPlanTabComponent" :total="total" :queryParams="queryParams" :getList="getList" />

总结:父组件通过“ : ”向子组件传递参数和方法,子组件通过props = defineProps({}),后期子组件直接通过 prop.page 使用参数

示例如下:

props.queryParams.pageNum = 1;
props.queryParams.planStatus = pane.paneName;
props.getList(); //使用父组件方法

二、emit==>向父组件发出 emit 事件(参数和方法事件)

子组件定义 emit 事件,在需要的地方调用 emit 事件向父组件发出 emit 事件;

事件可以分为两种一个是参数,一个是方法

案例一:v-model:propName 类型,实现数据的双向绑定

父组件

<TabComponent v-model:page="pageValue" ref="LegShippingPlanTabComponent" :queryParams="queryParams" :getList="getList" />

拓展知识点

这是 vue3 中的 v-model 中的新特性:

  • Vue 3 允许自定义组件有多个 v-model 绑定,语法格式为 v-model:propName
  • 默认 v-model (绑定到 modelValue):

子组件

先通过props = defineProps({})接收到数据,然后定义 emit()更新事件

const props = defineProps({total: propTypes.number,page: propTypes.number.def(1),limit: propTypes.number.def(20),pageSizes: {type: Array as PropType<number[]>,default: () => [10, 20, 30, 50]},
})
const emit = defineEmits(['update:page']);
//向父组件发出emit事件
const save=()=>{emit('update:page', val); //update:page发出这个事件,val是page的值;
}

总结:这里就实现了 父子组件的双向绑定;

案例二:子组件通过 emit 发送方法事件

子组件:

首先定义 emit 事件,然后调用 emit 发送事件

const props = defineProps({total: propTypes.number,page: propTypes.number.def(1),limit: propTypes.number.def(20),pageSizes: { //小驼峰type: Array as PropType<number[]>,default: () => [10, 20, 30, 50]}
});
const emit = defineEmits(['pagination']);
//发送emit事件,不传递参数
const handleAdd=()=>{emit('pagination')
}
//发送emit事件 可以传递参数
const handleSubmit=()=>{emit('pagination', { page: val, limit: pageSize.value });
}

父组件:

通过@ pagination 接收,父组件中的这个 pagination 的名字需要与子组件中的 emit 事件名称一样及const emit = defineEmits(['pagination']);

<pagination
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
:page-sizes="[10, 20, 50, 100, 500, 1000, 2000]"/>

总结:分为三步,一是子组件中定义emit事件;二是发出emit事件;三父组件通过@pagination响应


三、defineExpose

父组件调用子组件通过defineExpose 导出的方法)

子组件

通过defineExpose 导出(暴露)子组件的方法

<script setup name="LegShippingPlanTabComponent" lang="ts">
const getTabStatusCount = async () => {const res = await getTabCount();activeTabCount.value = res.data;
}defineExpose({getTabStatusCount,
})
</script>

父组件:

先定义一个 ref,然后通过.vale.getTabStatusCount()直接调用子组件的方法;

<TabComponent ref="LegShippingPlanTabComponent" :queryParams="queryParams" :getList="getList" />
<script setup name="LegShippingPlan" lang="ts">const LegShippingPlanTabComponent = ref()
/** 查询头程发货计划列表 */
const getList = async () => {await LegShippingPlanTabComponent.value.getTabStatusCount();
}</script>

总结:如果父组件需要用子组件defineExpose的方法,一定要在使用这个子组件中加一个 ref,通过它去调用子组件的方法;


四、实战案例

子组件

<script setup>
import { ref, watch } from 'vue';const props = defineProps({modelValue: Boolean, // 控制弹窗显示initialFormData: {   // 初始表单数据type: Object,default: () => ({processor: '',remark: ''})}
});const emit = defineEmits(['update:modelValue', 'submit']);// 表单数据
const paramsForm = ref({ ...props.initialFormData });// 表单引用(用于验证)
const formRef = ref(null);// 监听弹窗打开时重置表单
watch(() => props.modelValue, (visible) => {if (visible) {paramsForm.value = { ...props.initialFormData };}
});// 提交表单
const handleSubmit = async () => {try {// 表单验证await formRef.value.validate();// 提交数据并关闭弹窗emit('submit', { ...paramsForm.value });emit('update:modelValue', false);} catch (error) {console.error('表单验证失败:', error);}
};// 关闭弹窗
const closeDialog = () => {emit('update:modelValue', false);
};
</script><template><el-dialog:model-value="modelValue"@update:model-value="$emit('update:modelValue', $event)"title="转交处理人"width="500px"><el-formref="formRef":model="paramsForm"label-width="80px":rules="{processor: [{ required: true, message: '请选择处理人', trigger: 'blur' }]}"><el-form-item label="处理人" prop="processor"><el-selectv-model="paramsForm.processor"placeholder="请选择处理人"style="width: 100%"><el-option label="张三" value="zhangsan" /><el-option label="李四" value="lisi" /><el-option label="王五" value="wangwu" /></el-select></el-form-item><el-form-item label="备注"><el-inputv-model="paramsForm.remark"type="textarea"placeholder="请输入备注信息"/></el-form-item></el-form><template #footer><el-button @click="closeDialog">取消</el-button><el-button type="primary" @click="handleSubmit">确定</el-button></template></el-dialog>
</template>

父组件

<script setup>
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
import ChildDialog from './ChildDialog.vue';
import { updateProcessor } from '@/api/your-api'; // 替换为你的API// 控制弹窗显示
const dialogVisible = ref(false);// 父组件表单数据
const formData = ref({id: '',       // 假设有ID字段title: '',    // 其他表单字段processor: '', // 处理人remark: ''    // 备注
});// 打开弹窗
const openTransferDialog = () => {dialogVisible.value = true;
};// 接收子组件数据并发请求
const handleSubmit = async (transferData) => {try {// 1. 更新本地表单数据formData.value.processor = transferData.processor;formData.value.remark = transferData.remark;// 2. 调用API更新处理人const res = await updateProcessor({id: formData.value.id,processor: transferData.processor,remark: transferData.remark});// 3. 提示成功ElMessage.success('处理人更新成功');// 4. 可以在这里刷新数据或执行其他操作// fetchData();} catch (error) {ElMessage.error('更新处理人失败: ' + error.message);console.error('API请求错误:', error);}
};
</script><template><div class="parent-container"><!-- 主表单 --><el-form :model="formData" label-width="100px"><el-form-item label="标题"><el-input v-model="formData.title" disabled /></el-form-item><el-form-item label="当前处理人"><el-input v-model="formData.processor" disabled /></el-form-item><el-form-item><el-button type="primary" @click="openTransferDialog">转交处理人</el-button></el-form-item></el-form><!-- 子组件弹窗 --><ChildDialogv-model="dialogVisible"@submit="handleSubmit":initial-form-data="{processor: formData.processor,remark: formData.remark}"/></div>
</template><style scoped>
.parent-container {padding: 20px;max-width: 800px;margin: 0 auto;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/899679.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微前端实现方案对比Qiankun VS npm组件

架构层面&#xff1a; 1、Qiankun是典型的微前端架构&#xff0c;侧重构建多个独立前端应用协同工作的架构&#xff0c;主应用负责自用用的加载、卸载和通信&#xff1b;子应用不限制&#xff0c;可以是VUE、React等&#xff1b; 2、Qiankun松耦合&#xff0c;各个自应用独立…

可编辑160页PPT | 营销流程和管理数字化转型规划

荐言分享&#xff1a;随着技术的发展和消费者行为的变化&#xff0c;传统营销方式已难以满足现代企业的需求。企业需要借助数字化手段&#xff0c;对营销流程进行全面梳理和优化&#xff0c;提升营销活动的精准度和效率。同时&#xff0c;通过数字化营销管理&#xff0c;企业可…

Ecovadis认证需要准备哪些材料?

Ecovadis认证&#xff0c;作为全球领先的企业社会责任&#xff08;CSR&#xff09;评估平台&#xff0c;其准备材料的过程不仅需要详尽无遗&#xff0c;更要体现出企业在环境、社会、劳工和伦理四大方面的卓越实践与持续改进的决心。 首先&#xff0c;环境管理方面&#xff0c…

程序化广告行业(45/89):RTB竞价后续流程、结算规则及相关要点解读

程序化广告行业&#xff08;45/89&#xff09;&#xff1a;RTB竞价后续流程、结算规则及相关要点解读 大家好&#xff01;一直以来&#xff0c;我都希望能和大家一起在程序化广告这个领域不断探索、共同成长&#xff0c;这也是我写这系列博客的初衷。之前我们了解了程序化广告…

权重参数矩阵

目录 1. 权重参数矩阵的定义与作用 2. 权重矩阵的初始化与训练 3. 权重矩阵的解读与分析 (1) 可视化权重分布 (2) 统计指标分析 4. 权重矩阵的常见问题与优化 (1) 过拟合与欠拟合 (2) 梯度问题 (3) 权重对称性问题 5. 实际应用示例 案例1&#xff1a;全连接网络中的…

文法 2025/3/3

文法的定义 一个文法G是一个四元组&#xff1a;G(,,S,P) &#xff1a;一个非空有限的终极符号集合。它的每个元素称为终极符号或终极符&#xff0c;一般用小写字母表示。终极符号是一个语言不可再分的基本符号。 &#xff1a;一个非空有限的非终极符号集合。它的每个元素称为…

字符串复习

344:反转字符串 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间&#xff0c;你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 示例 1&#xff1a; 输入&#xff1a;s ["…

【数据结构】算法效率的双刃剑:时间复杂度与空间复杂度

前言 在算法的世界里&#xff0c;效率是衡量算法优劣的关键标准。今天&#xff0c;就让我们深入探讨算法效率的两个核心维度&#xff1a;时间复杂度和空间复杂度&#xff0c;帮助你在算法设计的道路上更进一步。 一、算法效率&#xff1a;衡量算法好坏的关键 算法的效率主要…

Java基础-26-多态-认识多态

在Java编程中&#xff0c;多态&#xff08;Polymorphism&#xff09; 是面向对象编程的核心概念之一。通过多态&#xff0c;我们可以编写更加灵活、可扩展的代码。本文将详细介绍什么是多态、如何实现多态&#xff0c;并通过具体的例子来帮助你更好地理解这一重要概念。 一、什…

使用自定义的RTTI属性对对象进行流操作

由于历史原因&#xff0c;在借鉴某些特定出名的游戏引擎中&#xff0c;不知道当时的作者的意图和编写方式 特此做这篇文章。&#xff08;本文出自游戏编程精粹4 中 使用自定义的RTTI属性对对象进行流操作 文章&#xff09; 载入和 保存 关卡&#xff0c;并不是一件容易办到的事…

周总结aa

上周学习了Java中有关字符串的内容&#xff0c;与其有关的类和方法 学习了static表示静态的相关方法和类的使用。 学习了继承(extends) 多态&#xff08;有继承关系&#xff0c;有父类引用指向子类对象&#xff09; 有关包的知识&#xff0c;final关键字的使用&#xff0c;及有…

密码学基础——密码学相关概念

目录 1.1 密码系统&#xff08;Cryptosystem&#xff09; 1.2 密码编码学 1.3 密码分析学 1.4 基于算法保密 1.5 基于密钥保密 1.6密码系统的设计要求 1.7 单钥体制 1.8 双钥体制 密钥管理 1.1 密码系统&#xff08;Cryptosystem&#xff09; 也称为密码体制&#xff0…

初始JavaEE篇 —— Mybatis-plus 操作数据库

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;JavaEE 目录 前言 Mybatis-plus 快速上手 Mybatis-plus 复杂操作 常用注解 TableName TableField TableId 打印日志 条件构造器 …

PyQt6实例_批量下载pdf工具_主线程启用线程池

目录 前置&#xff1a; 代码&#xff1a; 视频&#xff1a; 前置&#xff1a; 1 本系列将以 “PyQt6实例_批量下载pdf工具”开头&#xff0c;放在 【PyQt6实例】 专栏 2 本系列涉及到的PyQt6知识点&#xff1a; 线程池&#xff1a;QThreadPool,QRunnable&#xff1b; 信号与…

1.2 斐波那契数列模型:LeetCode 面试题 08.01. 三步问题

动态规划解三步问题&#xff1a;LeetCode 面试题 08.01. 三步问题 1. 题目链接 LeetCode 面试题 08.01. 三步问题 题目要求&#xff1a;小孩上楼梯&#xff0c;每次可以走1、2或3步&#xff0c;计算到达第 n 阶台阶的不同方式数&#xff0c;结果需对 1e9 7 取模。 2. 题目描述…

UE5 学习笔记 FPS游戏制作30 显示击杀信息 水平框 UI模板(预制体)

文章目录 一制作单条死亡信息框水平框的使用创建一个水平框添加子元素调整子元素顺序子元素的布局插槽尺寸填充对齐 制作UI 根据队伍&#xff0c;设置文本的名字和颜色声明变量 将变量设置为构造参数根据队伍&#xff0c;设置文本的名字和颜色在构造事件中&#xff0c;获取玩家…

HTTP---基础知识

天天开心&#xff01;&#xff01;&#xff01; 文章目录 一、HTTP基本概念1. 什么是HTTP&#xff0c;又有什么用&#xff1f;2. 一次HTTP请求的过程3.HTTP的协议头4.POST和GET的区别5. HTTP状态码6.HTTP的优缺点 二、HTTP的版本演进1.各个版本的应用场景2、注意要点 三、HTTP与…

数据结构 KMP 字符串匹配算法

KMP算法是计算机科学中的一种字符串匹配算法&#xff0c;KMP是三个创始人名字首字母 题目 AcWing - 算法基础课 前置知识点 KMP算法是一种高效的字符串匹配算法&#xff0c;算法名称取自于三位共同发明人名字的首字母组合。该算法的主要使用场景就是在字符串&#xff08;也叫…

Conda配置Python环境

1. 安装 Conda 选择发行版&#xff1a; Anaconda&#xff1a;适合需要预装大量科学计算包的用户&#xff08;体积较大&#xff09;。 Miniconda&#xff1a;轻量版&#xff0c;仅包含 Conda 和 Python&#xff08;推荐自行安装所需包&#xff09;。 验证安装&#xff1a; co…

数仓开发那些事(11)

某神州优秀员工&#xff1a;一闪&#xff0c;领导说要给我涨米。 一闪&#xff1a;。。。。&#xff08;着急的团团转&#xff09; 老运维&#xff1a;Oi&#xff0c;两个吊毛&#xff0c;看看你们的hadoop集群&#xff0c;健康度30分&#xff0c;怎么还在抽思谋克&#xff1f…