当前位置: 首页 > news >正文

[Vue3]父子组件相互传值数据同步

简介

vue3中使用setup语法糖,父子组件之间相互传递数据及数据同步问题

文章目录

  • 简介
  • 父传子
    • props传递值 使用v-bind绑定
      • props需要计算
        • toRef
        • computed
    • emit传递方法 使用v-on绑定
  • 子传父
    • expose
  • v-model
  • 总结


父传子

props传递值 使用v-bind绑定

父组件通过props给子组件传递值,props传递的值在子组件中无法修改

// 父组件
<template><div style="color: red">我是父组件<Child :msg="msg"></Child></div>
</template><script setup>import Child from './Child.vue';import { ref } from 'vue';const msg = ref('111');
</script>
// 子组件
<template><div style="color: blue"><div>我是子组件, 父组件传递来的值是{{msg}}</div></div>
</template><script setup>defineProps({msg: String,})
</script>

在这里插入图片描述

props需要计算

子组件获取props后,需要显示根据其计算后的值,而props是无法修改的。

toRef

props是具有响应式的,普通的解构和取值会失去响应式,所以下面这种情况只能取到props的初始值,如果props变化子组件不会更新:

// 父组件
<script setup>import Child from './Child.vue';import { ref } from 'vue';const msg = ref('111');
</script><template><div style="color: red">我是父组件{{ msg }}<Child :msg="msg"></Child><button @click="() => msg = '222'">父组件点击改变props值</button></div>
</template>
// 子组件
<script setup>import { ref } from 'vue'const props = defineProps({msg: String,})const a = ref(props.msg);
</script><template><div style="color: blue"><div>我是子组件, 父组件传递来的值是{{a}}</div></div>
</template>

点击按钮后,父组件传递的props改变,但是子组件接收到的却不变。
如果父组件中props没有赋初始值,在子组件中接收到的会是undefined。这是因为 ref 是对传入数据的拷贝,但 toRef 是对传入数据的引用。

// 子组件import { toRef } from 'vue'const props = defineProps({msg: String,})const a = toRef(props, 'msg');// const { msg } = toRefs(props); // 使用toRefs也可以

在这里插入图片描述

computed

根据props修改可以直接使用计算属性

// 父组件
<script setup>import Child from './Child.vue';import { ref } from 'vue';const msg = ref('A')
</script><template><div style="color: red">我是父组件{{ msg }}<Child :msg="msg"></Child><button @click="() => msg = 'B'">父组件点击改变props值</button></div>
</template>
// 子组件
<script setup>import { computed } from 'vue'const props = defineProps({msg: String,})const a = computed(() => props.msg.trim().toLowerCase())
</script><template><div style="color: blue"><div>我是子组件, 父组件传递来的值是{{ a }}</div></div>
</template>

在这里插入图片描述

emit传递方法 使用v-on绑定

vue3中子组件想调用父组件传递的方法,需要使用defineEmits

// 父组件
<script setup>import { ref } from 'vue';import Child from './Child.vue';const a = ref('1');const handleTest = () => {a.value = 'change';}
</script><template><div style="color: red">我是父组件<Child :msg="a" @test="handleTest"></Child></div>
</template>
// 子组件
<script setup>  defineProps(['msg']);const emit = defineEmits(["test"])const handleClick = () => {emit("test")}
</script><template><div style="color: blue"><div>我是子组件{{ msg }}</div><button @click="handleClick">子组件调用父组件方法</button></div>
</template>

在这里插入图片描述

emit的第一个参数是事件名,第二个参数是传递的参数。
这里如果父组件没有传递这个函数,也不会报错。

子传父

expose

父组件展示子组件的数据与方法,子组件需要通过defineExpose将自己的值暴露出来,父组件通过子组件上的ref取到其值

// 父组件
<script setup>import { ref, onMounted } from 'vue';import Child from './Child.vue';const a = ref('1');const x = ref();onMounted(()=>{a.value = x.value.message})const handle = () => {x.value.handleMessage();}
</script><template><div style="color: red">我是父组件<Child ref="x"></Child>{{ a }}<button @click="handle">点击子组件触发事件</button></div>
</template>
<script setup>import { ref } from "vue";const a = ref('我的值是1')const message = ref('我是子组件暴露的值');const handleMessage = () => {a.value = 'Change';}defineExpose({message,handleMessage});
</script><template><div style="color: blue">我是子组件{{ a }}</div>
</template>

在这里插入图片描述
父组件调用子组件expose的值,一定要在onMounted之后,否则子组件没有完全加载,取不到值。
这种方法,如果子组件的值修改了,那么父组件也是拿不到的。

v-model

使用v-model可以实现父子组件之间值的同步。

// 父组件
<script setup>
import Child from './Child.vue'
import { ref } from 'vue'const msg = ref('Hello World!')
</script><template><h1>{{ msg }}</h1><Child v-model="msg" />
</template>
// 子组件
<script setup>
const model = defineModel()
</script><template><span>My input</span> <input v-model="model">
</template>

在输入框中输入值,上面也会更新
defineModel是一个编译宏,它相当于:

// 子组件
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script><template><span>My input</span><input:value="props.modelValue"@input="emit('update:modelValue', $event.target.value)"/>
</template>

所以 v-model如果没有另外声明,实际是给子组件设置了一个名为modelValue的props,一个update:modelValue的emit(注意注意,emit调用时第一个参数一定要跟define时相同,否则找不到,update:后面也不要加空格)。

v-model其实相当于v-bindv-on的组合:

<template><h1>{{ msg }}</h1><Child :modelValue="msg" @update:modelValue="val => msg= val"></Child>
</template>

v-model会将modelValue这个props和update:modelValue这个event绑定在一起。当子组件的值发生变化时,会触发update:modelValue 事件传递给父组件,父组件接收到事件后会更新自己的值并重新渲染子组件;当父组件的值发生变化时,会通过modelValue传递给子组件,子组件接收到 prop 后会更新自己的值并重新渲染。这样就实现了父子组件之间的数据同步。

v-model可以写成v-model:自定义='自定义',那么更新的值就是自定义,更新的函数就是 update:自定义

总结

  • 父传子:definePropsdefineEmits
  • 子传父:defineExpose
  • 双向绑定:v-bind

vue中父子传值的方法还是非常多的,但是其中不乏各种坑,新手还是应该老老实实用官方推荐,否则真的很难不踩坑,太灵活了有些时候也是一种问题呢(无语笑)。

相关文章:

  • 【linux】通过脚本、系统服务监控开机时间和 cpu 温度
  • wins 安装 tensorflow keras
  • HuTool工具使用(JSONUtil+JSONObject+JSONArray)
  • 3593 蓝桥杯 查找最大元素 简单
  • Leetcode—42. 接雨水【困难】
  • 项目02《游戏-08-开发》Unity3D
  • HarmonyOS鸿蒙ArkTS证件照生成模板(适合二次开发,全套源码版)
  • 面试复盘6——后端开发
  • 进程控制(Linux)
  • 【蓝桥杯冲冲冲】[NOIP2003 普及组] 栈
  • C++ 语法文件
  • 【Golang】exec.command命令日志输出示例
  • Linux常见面试题汇总
  • Java学习七、类和对象
  • AJAX-URL查询参数
  • [Vue CLI 3] 配置解析之 css.extract
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 〔开发系列〕一次关于小程序开发的深度总结
  • Bootstrap JS插件Alert源码分析
  • Date型的使用
  • ES2017异步函数现已正式可用
  • flask接收请求并推入栈
  • k8s 面向应用开发者的基础命令
  • laravel with 查询列表限制条数
  • mysql 5.6 原生Online DDL解析
  • Yeoman_Bower_Grunt
  • 利用阿里云 OSS 搭建私有 Docker 仓库
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 云大使推广中的常见热门问题
  • 7行Python代码的人脸识别
  • 树莓派用上kodexplorer也能玩成私有网盘
  • ​iOS安全加固方法及实现
  • ​iOS实时查看App运行日志
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • # Swust 12th acm 邀请赛# [ A ] A+B problem [题解]
  • #pragam once 和 #ifndef 预编译头
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • $.ajax()
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (pojstep1.1.2)2654(直叙式模拟)
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (转)fock函数详解
  • (转)h264中avc和flv数据的解析
  • (转)shell调试方法
  • (转)机器学习的数学基础(1)--Dirichlet分布
  • ***监测系统的构建(chkrootkit )
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .Net Redis的秒杀Dome和异步执行
  • .NET/C# 项目如何优雅地设置条件编译符号?