[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变化子组件不会更新:

// 父组件
<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没有赋初始值,在子组件中接收到的会是undifined。这是因为 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中父子传值的方法还是非常多的,但是其中不乏各种坑,新手还是应该老老实实用官方推荐,否则真的很难不踩坑,太灵活了有些时候也是一种问题呢(无语笑)。

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

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

相关文章

春节宅家必备!仅需26元/月,与好友共战《幻兽帕鲁》!

开放世界游戏《幻兽帕鲁》1 月 19 日推出抢先体验版之后&#xff0c;热度连日居高不下&#xff0c;其发售仅 6 天销量就突破了 800 万份&#xff0c;在线人数更是突破了 200 万大关。 因为游戏自身优化问题&#xff0c;不少玩家也遭遇了卡顿、闪退、延迟高等问题。针对此&#…

无人机遥感技术在地质灾害监测应用分析,多旋翼无人机应急救援技术探讨

地质灾害是指在地球的发展演变过程中&#xff0c; 由各种自然地质作用和人类活动所形成的灾害性地质事件。给人民的生命和财产安全带来严重威胁&#xff0c;因此有必要开展地质灾害预测预报、灾害应急和风险区划 遥感技术的快速发展为我们提供了一种获取实时灾害信息的可靠手段…

PS一键磨皮插件Delicious Retouch for mac中文 支持PS2024

Delicious Retouch for Mac是一款优秀的Photoshop插件&#xff0c;专注于人像修饰。以下是该插件的一些主要特点和功能&#xff1a; 软件下载&#xff1a;Delicious Retouch for mac中文 支持PS2024 人像修饰工具&#xff1a;Delicious Retouch专注于人像修饰&#xff0c;提供了…

解决极狐GitLab release 关键字使用中 x509 证书不受信任的问题

release 关键是极狐GitLab CI/CD 中用来发布版本的一个关键字&#xff0c;通常用法如下&#xff1a; release_job:stage: releaseimage: registry.gitlab.com/gitlab-org/release-cli:latestrules:- if: $CI_COMMIT_TAG script:- echo "running release_…

开源软件:技术创新与应用的推动力量

文章目录 每日一句正能量前言开源软件如何推动技术创新开源软件的历史开源软件的开发模式开源软件与闭源软件源代码和开发许可维护特点、支持和成本开源软件的优势减少开支可定制性快速创新发展透明度和安全性 开源软件的应用 常见问题后记 每日一句正能量 不好等待运气降临&am…

【已解决】Oracle 12541 TNS 无监听程序

目录 1、找到Oracle监听服务&#xff08;OracleOraDb10g_homeTNLListener&#xff09;&#xff0c;停止运行 2、首先查看监听文件是否超过4G 3、修改配置文件 连接oracle突然报错&#xff0c;提示Oracle 12541 TNS 无监听程序&#xff0c;可以按照以下步骤解决 1、找到Ora…

【用Unity开发一款横板跳跃游戏部分需要学习的技术点指南】

*** 用Unity开发一款横板跳跃游戏部分需要学习的技术点指南 空洞骑士是一款基于横板平台跳跃的传统风格2D动作冒险游戏&#xff0c;庞大的游戏世界交错相通&#xff0c;玩家控制小虫子去探索幽深黑暗的洞穴&#xff0c;成为了一代人茶余饭后的惦念&#xff0c;深受玩家喜爱。 …

【C++】类和对象3:默认成员函数之构造函数

前言 今天来初步了解一下类的6个默认成员函数 引入 默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器会生成的成员函数称为默认成员函数 下面是六个默认成员函数的图解 构造函数 概念 class Date { public:void Init(int year, int month, int day){_year …

layui

基于复杂结构的自定义模版相关介绍 我这里的接口给的格式数据 我这里搜索往返时候要显示成这样的 layui.use([table,form], function(){ var table layui.table; var form layui.form;// 渲染表格 table.render({ elem: #test-table-reload,toolbar: #toolbarDemo, …

2023年全球软件架构师峰会(ArchSummit上海站):核心内容与学习收获(附大会核心PPT下载)

微服务架构是当今软件架构的主流趋势之一。随着云计算和分布式系统的普及&#xff0c;越来越多的企业开始采用微服务架构来构建他们的应用。微服务架构可以将一个大型的应用拆分成多个小型的服务&#xff0c;每个服务都独立部署、独立运行&#xff0c;并通过轻量级的通信协议进…

如何使用第三方API采集电商数据呢?

电商商家最常唠叨的就是店铺运营难做。每日多平台店铺数据统计汇总繁琐耗时&#xff0c;人工效率偏低&#xff0c;且工作内容有限。 特别是眼下“618&#xff0c;双十一&#xff0c;双十二&#xff0c;年底大促”将至&#xff0c;如何提高运营的效率和质量、保证产品及服务的良…

cesium-水平测距

cesium测量两点间的距离 <template><div id"cesiumContainer" style"height: 100vh;"></div><div id"toolbar" style"position: fixed;top:20px;left:220px;"><el-breadcrumb><el-breadcrumb-item&…