前言
最近在想做个cloud项目,gitee上找了个模板项目,前端使用到vue3 + typeScript,最近使用到vue3 的父子组件之间的传值,顺便学习一下,在此总结一下,若有不足之处,望大佬们可以指出。
vue3官网:https://cn.vuejs.org/
一、父向子组件传值
父组件传递参数
<template><div><!-- 子组件 参数:num 、nums --><child:num="nums.num":doubleNum="nums.doubleNum"@increase="handleIncrease"></child></div></template><scriptsetuplang="ts">import child from'./child.vue';import{ ref,reactive }from'vue';// 对象默认const nums =reactive({num:0,doubleNum:0});// 点击事件consthandleIncrease=()=>{// 每次+1
nums.num++// 每次+2
nums.doubleNum +=2};</script>
子组件接收参数
defineEmits: defineEmits() 宏仅限于 setup 语法糖 使用,用来声明组件要触发的事件。
<template><div><span>点击次数:{{ props.num }}</span><br/><span>双倍次数:{{ props.doubleNum }}</span><br/><el-button@click="handelClick">点击</el-button></div></template><scriptsetuplang="ts">import{ ref }from'vue';// 声明组件要触发的事件const emits =defineEmits(['increase']);// 声明接收参数const props =defineProps({num: String,doubleNum: String
});// 点击事件consthandelClick=()=>{
console.log('触发子组件点击')// 触发父组件事件emits('increase')};</script>
父组件小优化
官方文档:https://cn.vuejs.org/guide/components/props.html#prop-passing-details
<template><div><!-- 子组件 参数:对象 --><childv-bind="nums"@increase="handleIncrease"></child></div></template>
这实际上等价于:
<template><div><!-- 子组件 参数:num 、nums --><child:num="nums.num":doubleNum="nums.doubleNum"@increase="handleIncrease"></child></div></template>
实现效果
二、子向父组件传值
子组件传递参数
<template><div><el-inputv-model="dataForm.name"placeholder="请输入我的名字"style="width: 120px"/><br/><el-inputv-model="dataForm.age"placeholder="请输入我的年龄"style="width: 120px"/><br/><el-button@click="handelClick">完成</el-button></div></template><scriptsetuplang="ts">import{ ref, reactive }from'vue';const emits =defineEmits(['increase']);// 对象const dataForm =reactive({name:'',age:''})consthandelClick=()=>{
console.log('触发子组件点击', dataForm.name,' ', dataForm.age)// 传递对象emits('increase',dataForm)};</script>
父组件接收参数
<template><div><!-- 子组件 触发事件:handleIncrease --><child@increase="handleIncrease"></child><br/>
我是父组件,我接收到的参数:<spanv-if="data.name">姓名:{{data.name}}</span><spanv-if="data.age">, 年龄:{{data.age}}</span></div></template><scriptsetuplang="ts">import child from'./child.vue';import{ ref,reactive }from'vue';// 接收对象封装const data =reactive({name:'',age:''});// 点击事件consthandleIncrease=(val: any)=>{
data.name = val.name
data.age = val.age
};</script>
实现效果
三、 defineExpose 方式(常用)
概述: 这是我在 clone 项目模板中看到的使用方式,也属于最常用的方式。
父向组件传值
<template><div><!-- 子组件 ref:data --><childref="data"></child><br/><span>我是父组件</span>
// 输入姓名
<el-inputv-model="name"placeholder="请输入我的姓名"style="width: 120px"/>
// 点击完成
<el-button@click="handelClick()">完成</el-button></div></template><scriptsetuplang="ts">import child from'./child.vue';import{ ref,reactive }from'vue';// 绑定的dataconst data =ref()// 姓名事件const name =ref(''as string)// 点击完成事件consthandelClick=()=>{
console.log('name:', name.value)// 初始化
data.value.init(name.value)
console.log('data: ', data.value)}</script>
子组件接收值
<template><div><span>我是子组件</span><el-inputv-model="dataForm.name"placeholder="请输入我的名字"style="width: 120px"/><br/><el-inputv-model="dataForm.age"placeholder="请输入我的年龄"style="width: 120px"/><br/></div></template><scriptsetuplang="ts">import{ ref, reactive }from'vue';// 组件对应的数据const dataForm =reactive({name:'',age:''})// 假设后端返回listconstlistDate: Array<object>=[{name:"lanys",age:23}]// 初始化方法 name 指的就是父组件传过来的nameconstinit=(name: string)=>{if(name){
listDate.forEach((val: any)=>{// 如果name 相同就 渲染 就类似更新功能if(val.name === name){
dataForm.name = val.name
dataForm.age = val.age
}})}}// 暴露组件defineExpose({init})</script>
实现效果
父组件输入 lanys
点击完成
这么设计的好处是什么?
从项目中能看出新增和更新功能可以做到通用,节省开发时间及成本。项目中是这么设计的,
在子组件 init(初始化中)
constinit=(id?: number)=>{// id 存在则为修改if(id){getUser(id)}// 获取下面的列表数据 可以忽略getOrgList()// 忽略getPostList()// 忽略getRoleList()}// 暴露组件defineExpose({
init
})
新增模块(不需要传id)
更新模块(传id)
版权归原作者 sout-lanys 所有, 如有侵权,请联系我们删除。