Vue3中的常见组件通信之`$refs`、`$parent`

2024-06-09 11:52

本文主要是介绍Vue3中的常见组件通信之`$refs`、`$parent`,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Vue3中的常见组件通信之$refs$parent

概述

​ 在vue3中常见的组件通信有props、mitt、v-model、 r e f s 、 refs、 refsparent、provide、inject、pinia、slot等。不同的组件关系用不同的传递方式。常见的撘配形式如下表所示。

组件关系传递方式
父传子1. props
2. v-model
3. $refs
4. 默认插槽、具名插槽
子传父1. props
2. 自定义事件
3. v-model
4. $parent
5. 作用域插槽
祖传孙、孙传祖1. $attrs
2. provide、inject
兄弟间、任意组件间1. mitt
2. pinia

props和自定义事件详见:
Vue3中的常见组件通信之props和自定义事件
mitt用法详见:
Vue3中的常见组件通信之mitt
v-model用法详见:
Vue3中的常见组件通信之v-model
$attrs用法详见:
Vue3中的常见组件通信之$attrs

接下来是$refs$parent

6. r e f s 、 refs、 refsparent

$refs用于父传子,$parent用于子传父。

6.1准备组件

准备三个组件,一个父组件,两个子组件。

父组件代码:

<template><div class="Father"><div id="d1"><h3>这是父组件</h3>存款:{{ money }} 万元</div><Child1/><Child2/></div>	
</template><script setup lang="ts" name="Father">
import Child1 from './Child1.vue'
import Child2 from './Child2.vue'
import {ref} from 'vue'//数据
let money = ref(100)</script><style scoped>.Father{background-color: rgb(155, 162, 168);padding: 10px;margin: 10px;}#d1{margin-left: 10px;}
</style>

子组件1代码:

<template><div class="Child1"><h3>这是子组件1</h3><ul><li>书籍:{{ book }} 本</li><li>玩具:{{ toy }}</li></ul></div></template><script setup lang="ts" name="Child1">
import {ref} from 'vue'//数据
let book = ref(10)
let toy = ref('滑板车')</script><style scoped>.Child1{background-color: rgb(132, 114, 148);margin: 10px 0;padding: 10px;color: white;}
</style>

子组件2代码:

<template><div class="Child2"><h3>这是子组件2</h3><ul><li>书籍:{{ book }} 本</li><li>玩具:{{ toy }}</li></ul></div>	
</template><script setup lang="ts" name="Child2">
import {ref} from 'vue'//数据
let book = ref(6)
let toy = ref('水枪')</script><style scoped>.Child2{background-color: rgb(128, 132, 31);margin-top: 10px;padding: 10px;color:white}
</style>

运行效果如下:

image-20240607145314586

6.2$refs实现父传子通信

需要先了解标签的ref属性的基本知识,ref用在普通DOM标签上,获取的是DOM节点;ref用在组件标签上,获取的是组件实例对象。

了解上面的基础知识后,要在父组件中创建c1和c2,用来存储ref标记的内容:

//创建c1和c2,用于存储ref标记的内容
let c1 = ref()
let c2 = ref()

在CHild1和Ch2组件标签上添加ref属性:

<Child1 ref="c1"/>
<Child2 ref="c2"/>

在Child1和Child2的组件内需要添加以下代码,用来把数据交出去:

//把数据交出去
defineExpose({book,toy})

此时,在父组件中已经拿到了子组件中的数据,可以对这些数据进行操作,如下代码定义一个函数,用来改变子组件1中的toy的值:

function changeC1Toy(){c1.value.toy = '积木'
}

在父组件创建按钮,并绑定click事件,用来触发 changeC1Toy函数:

<button @click="changeC1Toy">修改子组件1中的玩具</button>

运行后效果如下:

$refs可以在父组件中获取所有的用ref标记的子组件的实例对象,如果没有用ref标记,则获取不到,例如再增加一个子组件Child3,代码如下:

<template><div class="Child3"><h3>这是子组件3</h3><ul><li>书籍:{{ book }} 本</li><li>玩具:{{ toy }}</li></ul></div></template><script setup lang="ts" name="Child3">
import {ref} from 'vue'//数据
let book = ref(30)
let toy = ref('毛绒玩具')//把数据交出去
defineExpose({book,toy})
</script><style scoped>.Child3{background-color: rgb(120, 148, 114);margin: 10px 0;padding: 10px;color: white;}
</style>

在父组件中引入子组件3:

import Child3 from './Child3.vue'

在页面呈现,但是不添加ref属性

<Child3 />

接下来给父组件创建一个按钮,并绑定click事件,触发changeAllBook()函数,并传入$refs

<button @click="changeAllBook($refs)">修改子组件的书籍数量</button>

changeAllBook的函数代码如下:

function changeAllBook(refs:any){console.log(refs)for (let key in refs){refs[key].book += 1}
}

运行后点击按钮,控制台打印的内容如下:

image-20240608161927543

可以看到$refs是一个响应式的对象,对象内是c1和c2,没有子组件3的实例对象。通过遍历把c1和c2中的book增加1,运行效果如下图:

以上通过操控父组件的按钮,实现改变子组件中书籍的数量,这便是父传子通信的一种。

6.3$parent实现子传父通信

$parent的用法与$refs用法类似,$parent获取的是父组件的实例对象,如下在子组件1中添加一个按钮,并绑定单击事件,触发minusMoney方法,实现减少父组件中的存款:

<button @click="minusMoney($parent)">减少父组件存款</button>

minusMoney的代码如下:

function minusMoney(parent:any){	parent.money -= 1
}

父组件需要写个宏函数把数据交出去:

//将数据交出去
defineExpose({money})

至此已经完成了子传父的通信,点击子组件中的按钮,可以对父组件中的数据进行操控,如下图:

6.4小结

以上便是$refs$parent实现父子间通信的用法,小结如下:

**$refs:**用来获取所有用ref标记的子组件的实例对象,得到的是响应式对象数据类型,不能获取没有用ref标记的子组件实例对象。

**$parent:**用来获取父组件的实例对象。

注意:组件中需要用宏函数defineExpose()把数据交出去,不然获取不到数据。

以下是完整代码:

父组件:

<template><div class="Father"><div id="d1"><h3>这是父组件</h3>存款:{{ money }} 万元</div><button @click="changeC1Toy">修改子组件1中的玩具</button><button @click="changeAllBook($refs)">修改子组件的书籍数量</button><!-- 组件标签的ref属性获取的是组件的实例对象 --><Child1 ref="c1"/><Child2 ref="c2"/><Child3 /></div>	
</template><script setup lang="ts" name="Father">
import Child1 from './Child1.vue'
import Child2 from './Child2.vue'
import Child3 from './Child3.vue'
import {ref} from 'vue'//数据
let money = ref(100)//创建c1和c2,用于存储ref标记的内容
let c1 = ref()
let c2 = ref()//方法
function changeC1Toy(){c1.value.toy = '积木'
}function changeAllBook(refs:any){// console.log(refs)for (let key in refs){refs[key].book += 1}
}//将数据交出去
defineExpose({money})
</script><style scoped>.Father{background-color: rgb(155, 162, 168);padding: 10px;margin: 10px;}#d1{margin-left: 10px;}
</style>

子组件1

<template><div class="Child1"><h3>这是子组件1</h3><ul><li>书籍:{{ book }} 本</li><li>玩具:{{ toy }}</li></ul><button @click="minusMoney($parent)">减少父组件存款</button></div>
</template><script setup lang="ts" name="Child1">
import {ref} from 'vue'//数据
let book = ref(10)
let toy = ref('滑板车')//方法
function minusMoney(parent:any){	parent.money -= 1
}//把数据交出去
defineExpose({book,toy})
</script><style scoped>.Child1{background-color: rgb(132, 114, 148);margin: 10px 0;padding: 10px;color: white;}button{color: #000;}
</style>

子组件2

<template><div class="Child2"><h3>这是子组件2</h3><ul><li>书籍:{{ book }} 本</li><li>玩具:{{ toy }}</li></ul></div>	
</template><script setup lang="ts" name="Child2">
import {ref} from 'vue'//数据
let book = ref(6)
let toy = ref('水枪')//把数据交出去
defineExpose({book,toy})
</script><style scoped>.Child2{background-color: rgb(128, 132, 31);margin-top: 10px;padding: 10px;color:white}
</style>

这篇关于Vue3中的常见组件通信之`$refs`、`$parent`的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1045107

相关文章

SQL中redo log 刷⼊磁盘的常见方法

《SQL中redolog刷⼊磁盘的常见方法》本文主要介绍了SQL中redolog刷⼊磁盘的常见方法,将redolog刷入磁盘的方法确保了数据的持久性和一致性,下面就来具体介绍一下,感兴趣的可以了解... 目录Redo Log 刷入磁盘的方法Redo Log 刷入磁盘的过程代码示例(伪代码)在数据库系统中,r

HTML5中的Microdata与历史记录管理详解

《HTML5中的Microdata与历史记录管理详解》Microdata作为HTML5新增的一个特性,它允许开发者在HTML文档中添加更多的语义信息,以便于搜索引擎和浏览器更好地理解页面内容,本文将探... 目录html5中的Mijscrodata与历史记录管理背景简介html5中的Microdata使用M

html5的响应式布局的方法示例详解

《html5的响应式布局的方法示例详解》:本文主要介绍了HTML5中使用媒体查询和Flexbox进行响应式布局的方法,简要介绍了CSSGrid布局的基础知识和如何实现自动换行的网格布局,详细内容请阅读本文,希望能对你有所帮助... 一 使用媒体查询响应式布局        使用的参数@media这是常用的

HTML5表格语法格式详解

《HTML5表格语法格式详解》在HTML语法中,表格主要通过table、tr和td3个标签构成,本文通过实例代码讲解HTML5表格语法格式,感兴趣的朋友一起看看吧... 目录一、表格1.表格语法格式2.表格属性 3.例子二、不规则表格1.跨行2.跨列3.例子一、表格在html语法中,表格主要通过< tab

SQL BETWEEN 的常见用法小结

《SQLBETWEEN的常见用法小结》BETWEEN操作符是SQL中非常有用的工具,它允许你快速选取某个范围内的值,本文给大家介绍SQLBETWEEN的常见用法,感兴趣的朋友一起看看吧... 在SQL中,BETWEEN是一个操作符,用于选取介于两个值之间的数据。它包含这两个边界值。BETWEEN操作符常用

python中各种常见文件的读写操作与类型转换详细指南

《python中各种常见文件的读写操作与类型转换详细指南》这篇文章主要为大家详细介绍了python中各种常见文件(txt,xls,csv,sql,二进制文件)的读写操作与类型转换,感兴趣的小伙伴可以跟... 目录1.文件txt读写标准用法1.1写入文件1.2读取文件2. 二进制文件读取3. 大文件读取3.1

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

前端CSS Grid 布局示例详解

《前端CSSGrid布局示例详解》CSSGrid是一种二维布局系统,可以同时控制行和列,相比Flex(一维布局),更适合用在整体页面布局或复杂模块结构中,:本文主要介绍前端CSSGri... 目录css Grid 布局详解(通俗易懂版)一、概述二、基础概念三、创建 Grid 容器四、定义网格行和列五、设置行

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a