【Vue】Vue3.0(二十四)Vue3.0中$refs 、$parent 的概念和使用场景

文章目录

一、 r e f s 和 refs和 refsparent的概念及使用场景

1. $refs概念及使用场景
  • 概念:在Vue 3.0里,$refs是一个比较特殊的属性,它的主要作用是让我们能够访问到组件实例或者DOM元素。具体来讲,当我们在模板中给一个组件或者DOM元素设置了ref属性之后,就可以通过组件实例的$refs这个对象来拿到对该组件或者DOM元素的引用啦。
  • 使用场景
    • 访问子组件实例:在父组件当中,常常会用到$refs来获取子组件的实例哦。为什么要这么做呢?因为这样一来,父组件就可以直接去访问子组件内部的数据,还能调用子组件的方法呢。比如说,在一些场景下,父组件需要根据用户的操作来触发子组件里的某个特定方法,或者要获取子组件中的某个数据值以便做进一步的处理,这时候$refs就派上大用场啦。
    • 操作DOM元素:除了获取子组件实例,$refs还有个用处就是能拿到对普通DOM元素的引用哦。有了这个引用,我们就可以直接对DOM元素进行一些操作啦,比如获取输入框里的值呀,或者给元素设置样式之类的。不过呢,在Vue的开发理念里,通常还是建议尽量通过数据绑定和响应式机制来操作视图哦,直接去操作DOM元素的情况相对来说是比较少的,但在某些特定的需求下,还是会用到$refs来操作DOM元素的呢。
2. $parent概念及使用场景
  • 概念$parent是一个组件实例的属性哦,它是指向当前组件的父组件实例的。通过$parent这个属性,子组件就能够去访问父组件的属性,还能调用父组件的方法呢,这样就实现了子组件和父组件之间从子到父方向的通信啦。
  • 使用场景
    • 子组件修改父组件数据:有时候子组件需要根据自己这边的操作来更新父组件里的某些数据呀,这时候就可以利用$parent来访问父组件实例,然后进而去修改父组件的数据哦。比如说,子组件里的某个操作可能会影响到父组件展示的总体数据状态,那通过$parent就能很方便地实现这种跨组件的数据更新啦。
    • 子组件调用父组件方法:同样的道理,子组件要是需要触发父组件中定义的某个方法来完成特定的业务逻辑,比如子组件完成了某项任务之后要通知父组件接着做后续处理呀,这时候就可以通过$parent来调用父组件的方法啦。

二、代码解释

Father.vue
<template><div class="father"><h3>父组件</h3><h4>房产:{{ house }}</h4><button @click="changeToy">修改Child1的玩具</button><button @click="changeComputer">修改Child2的电脑</button><button @click="getAllChild($refs)">让所有孩子的书变多</button><Child1 ref="c1" /><Child2 ref="c2" /></div>
</template><script setup lang="ts" name="Father">
import Child1 from './Child1.vue'
import Child2 from './Child2.vue'
import { ref, reactive } from "vue";
let c1 = ref()
let c2 = ref()// 注意点:当访问obj.c的时候,底层会自动读取value属性,因为c是在obj这个响应式对象中的
/* let obj = reactive({a:1,b:2,c:ref(3)
})
let x = ref(4)console.log(obj.a)
console.log(obj.b)
console.log(obj.c)
console.log(x) */// 数据
let house = ref(4)
// 方法
function changeToy() {c1.value.toy = '小猪佩奇'
}
function changeComputer() {c2.value.computer = '华为'
}
function getAllChild(refs: { [key: string]: any }) {console.log(refs)for (let key in refs) {refs[key].book += 3}
}
// 向外部提供数据
defineExpose({ house })
</script><style scoped>
.father {background-color: rgb(165, 164, 164);padding: 20px;border-radius: 10px;
}.father button {margin-bottom: 10px;margin-left: 10px;
}
</style>
  • Father.vue这个组件里面呢:
    • 使用$refs获取子组件实例并操作
      • 在模板部分呀,给Child1组件设置了ref="c1"这个属性,给Child2组件设置了ref="c2"属性。这么做了之后呢,在父组件的脚本部分就能通过 r e f s 来拿到这两个子组件的实例啦。比如说,在 c h a n g e T o y 这个方法里面,通过 ‘ c 1. v a l u e . t o y = ′ 小猪佩 奇 ′ ‘ 就把 ‘ C h i l d 1 ‘ 组件里的 ‘ t o y ‘ 数据给修改了;在 ‘ c h a n g e C o m p u t e r ‘ 方法里,通过 ‘ c 2. v a l u e . c o m p u t e r = ′ 华 为 ′ ‘ 就把 ‘ C h i l d 2 ‘ 组件里的 ‘ c o m p u t e r ‘ 数据给修改了。这里的 ‘ c 1. v a l u e ‘ 和 ‘ c 2. v a l u e ‘ 其实就是通过 ‘ refs来拿到这两个子组件的实例啦。比如说,在changeToy这个方法里面,通过`c1.value.toy = '小猪佩奇'`就把`Child1`组件里的`toy`数据给修改了;在`changeComputer`方法里,通过`c2.value.computer = '华为'`就把`Child2`组件里的`computer`数据给修改了。这里的`c1.value`和`c2.value`其实就是通过` refs来拿到这两个子组件的实例啦。比如说,在changeToy这个方法里面,通过c1.value.toy=小猪佩就把Child1‘组件里的toy数据给修改了;在changeComputer方法里,通过c2.value.computer=就把Child2‘组件里的computer数据给修改了。这里的c1.valuec2.value其实就是通过refs`获取到的子组件实例呀,拿到实例之后呢,就可以像操作普通对象一样去操作它们内部的数据啦。
      • 在getAllChild这个方法里呢,参数refs: { [key: string]: any }接收的就是通过$refs获取到的所有带有ref属性的组件或者元素的引用对象哦。然后通过遍历这个对象,对每个子组件实例的book数据都进行了修改(refs[key].book += 3),这样就实现了对所有子组件中book数据的统一操作啦。
    • 向外部提供数据:通过defineExpose({ house })这句代码呀,父组件就把house这个数据给暴露出去啦,这样在其他需要的时候,比如可能存在的更外层的组件呀,就可以获取到这个数据啦。
Child1.vue
<template><div class="child1"><h3>子组件1</h3><h4>玩具:{{ toy }}</h4><h4>书籍:{{ book }}</h4><button @click="minusHouse($parent)">干掉父亲的一套房产</button></div>
</template><script setup lang="ts" name="Child1">
import { ref } from "vue";
// 数据
let toy = ref('奥特曼')
let book = ref(3)// 方法
function minusHouse(parent: any) {parent.house -= 1
}// 把数据交给外部
defineExpose({ toy, book })</script><style scoped>
.child1 {margin-top: 20px;background-color: skyblue;padding: 20px;border-radius: 10px;box-shadow: 0 0 10px black;
}
</style>

Child1.vue组件这里呢:
使用 p a r e n t 访问父组件并修改数据:在 m i n u s H o u s e 这个方法里面,通过 p a r e n t . h o u s e − = 1 就把父组件 F a t h e r . v u e 里的 h o u s e 数据给修改了。这里的 p a r e n t 其实就是通过 parent访问父组件并修改数据 : 在minusHouse这个方法里面,通过parent.house -= 1就把父组件Father.vue里的house数据给修改了。这里的parent其实就是通过 parent访问父组件并修改数据:在minusHouse这个方法里面,通过parent.house=1就把父组件Father.vue里的house数据给修改了。这里的parent其实就是通过parent获取到的父组件实例哦,通过这样的方式呢,就实现了子组件对父组件数据的反向操作啦。
向外部提供数据:
同样也是通过defineExpose({ toy, book })这句代码呀,把toy和book这两个数据给暴露出去啦,这样其他组件要是想获取或者操作这两个数据就方便多啦。

Child2.vue
<template><div class="child2"><h3>子组件2</h3><h4>电脑:{{ computer }}</h4><h4>书籍:{{ book }}</h4></div>
</template><script setup lang="ts" name="Child2">
import { ref } from "vue";
// 数据
let computer = ref('联想')
let book = ref(6)
// 把数据交给外部
defineExpose({ computer, book })
</script><style scoped>
.child2 {margin-top: 20px;background-color: orange;padding: 20px;border-radius: 10px;box-shadow: 0 0 10px black;
}
</style>
  • Child2.vue组件里呢,通过defineExpose({ computer, book })把computer和book这两个数据给暴露出去啦,虽然这里不像Child1.vue那样通过$parent和父组件进行交互呀,但也是遵循了把组件内部数据合理暴露出去以便外部使用的这么一个原则哦。

三、新的例子

假设我们现在有一个简单的计数器应用哦,它包含了一个父组件CounterParent.vue以及两个子组件CounterIncrement.vue(这个子组件是用来增加计数的)和CounterDecrement.vue(这个子组件是用来减少计数的)。

CounterParent.vue
<template><div class="counter-parent"><h2>计数器:{{ count }}</h2><CounterIncrement ref="incrementRef" /><CounterDecrement ref="decrementRef" /></div>
</template><script setup lang="ts">
import CounterIncrement from './CounterIncrement.vue';
import CounterDecrement from './CounterDecrement.vue';
import { ref } from 'vue';let count = ref(0);
let incrementRef = ref();
let decrementRef = ref();// 当点击增加按钮时,调用子组件的增加方法并更新计数
const incrementCount = () => {incrementRef.value.increment();count.value++;
};// 当点击减少按钮时,调用子组件的减少方法并更新计数
const decrementCount = () => {decrementRef.value.decrement();count.value--;
};
</script><style scoped>
.counter-parent {background-color: lightgray;padding: 20px;border-radius: 10px;
}
</style>

CounterParent.vue这个组件里面呢:

  • 首先定义了count作为计数器的初始值哦,并且通过ref创建了incrementRef和decrementRef这两个东西,它们的作用就是用来获取那两个子组件的实例呀。
  • 然后呢,incrementCount这个方法呀,它是通过$refs拿到CounterIncrement.vue子组件的实例(也就是incrementRef.value),然后调用它的increment方法来增加计数的哦,同时呢,还会把父组件中的count值也给更新一下。
  • 同样的,decrementCount这个方法呢,也是通过$refs拿到CounterDecrement.vue子组件的实例(也就是decrementRef.value),调用它的decrement方法来减少计数的哦,并且也会更新count值呢。
CounterIncrement.vue
<template><button @click="increment">增加计数</button>
</template><script setup lang="ts">
import { defineExpose } from 'vue';// 定义增加计数的方法
const increment = () => {// 这里可以添加一些额外的逻辑,比如发送通知等console.log('计数增加');
};// 向外部暴露增加计数的方法
defineExpose({ increment });
</script><style scoped>
button {margin-right: 10px;
}
</style>

CounterIncrement.vue这个组件里面呢:

  • 首先定义了increment这个方法呀,它的作用就是用来增加计数的哦。
  • 然后通过defineExpose({ increment })这句代码呀,就把increment这个方法给暴露出去啦,这样父组件就能够调用这个方法啦。
CounterDecrement.vue
<template><button @click="decrement">减少计数</button>
</template><script setup lang="ts">
import { defineExpose } from 'vue';// 定义减少计数的方法
const decrement = () => {// 以下可以添加一些额外的逻辑,比如发送通知等console.log('计数减少');
};// 向外部暴露减少计数的方法
defineExpose({ decrement });
</script><style scoped>
button {margin-right: 10px;
}
</style>

CounterDecrement.vue这个组件里面呢:

  • 首先定义了decrement这个方法呀,它的作用就是用来减少计数的哦。
  • 然后通过defineExpose({ decrement })这句代码呀,就把decrement这个方法给暴露出去啦,这样父组件就能够调用这个方法啦。

在这个新例子里面呢,通过$refs实现了父组件对子组件方法的调用呀,这样就完成了计数器的增加和减少操作啦;同时呢,子组件通过defineExpose把内部方法暴露给父组件,这也是遵循了Vue 3.0组件间交互的规范哦。

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

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

相关文章

kubesphere环境-本地Harbor仓库+k8s集群(单master 多master)+Prometheus监控平台部署

前言&#xff1a;半月前在公司生产环境上离线部署了k8s集群Victoria Metrics(二开版)自研版夜莺 监控平台的搭建&#xff0c;下面我租用3台华为云服务器演示部署kubesphere环境-本地Harbor仓库k8s集群&#xff08;单master节点 & 单master节点&#xff09;Prometheus监控部…

java 随机生成验证码

1.需求 实现随机生成验证码&#xff0c;验证码可能是大小写字母和数字 2.实现 写一个getCode方法实现 public static String getCode(int n){//1. 定义一个字符串&#xff0c;字符串中包含大小写字母和数字String str "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs…

Unity图形学之Blend指令

1.渲染流程&#xff1a;Blend 决定了要渲染的像素和Gbuffer里像素到底怎么取舍 2.Blend 公式&#xff1a; 3.factor可以取值的内容有&#xff1a; One 1 Zero :0 SrcColor : 要渲染的像素 SrcAlpha : 要渲染像素的 a 通道。 DstColor &#xff1a; 已经渲染在gbuffer…

林曦词典|养生

“林曦词典”是在水墨画家林曦的课堂与访谈里&#xff0c;频频邂逅的话语&#xff0c;总能生发出无尽的思考。那些悠然轻快的、微妙纷繁的&#xff0c;亦或耳熟能详的词&#xff0c;经由林曦老师的独到解析&#xff0c;意蕴无穷&#xff0c;让人受益。于是&#xff0c;我们将诸…

生成自签名证书并配置 HTTPS 使用自签名证书

生成自签名证书 1. 运行 OpenSSL 命令生成证书和私钥 在终端中输入以下命令&#xff0c;生成自签名证书和私钥文件&#xff1a; sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout self_signed.key -out self_signed.pem-x509&#xff1a;生成自签名证书。…

物料数据对接:轻易云助力聚水潭与金蝶云星空集成方案

聚水潭数据集成到金蝶云星空&#xff1a;物料对接方案 在企业信息化系统中&#xff0c;数据的高效流动和准确对接是业务运营的关键。本文将聚焦于一个具体的技术案例——如何通过轻易云数据集成平台实现聚水潭与金蝶云星空之间的物料数据对接。 本次集成任务主要涉及两个核心…

阅读2020-2023年《国外军用无人机装备技术发展综述》笔记_作战无人机和察打无人机图鉴

文献基本信息 题名作者来源发表时间2020年国外先进军用无人机技术发展综述 袁成;董晓琳;朱超磊 飞航导弹 2021-01-14 2021年国外军用无人机装备技术发展综述 朱超磊 ;袁成;杨佳会;飞航导弹 战术导弹技术2022-02-112022年国外军用无人机装备技术发展综述 朱超磊;金钰;王靖…

【C#设计模式(11)——外观模式(Facade Pattern)】

前言 外观模式隐藏了子系统的复杂性&#xff0c;简化了客户端与子系统之间的交互。 代码 public class Facade{private CommunicationModel communicationModel;private AcquisitionModel acquisitionModel;private ToolModel toolModel;public Facade(){communicationModel n…

学习日记_20241115_聚类方法(层次聚类)

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…

力扣 LeetCode 239. 滑动窗口最大值(Day5:栈与队列)

解题思路&#xff1a; 始终维护deque的头元素为最大值&#xff0c;后面来的值更大就会逐一清除前面比它小的值 可以把 peek() 改为 peekFirst() &#xff0c;虽然是一个意思&#xff0c;但看起来更加清楚&#xff0c;对于双端队列能更清晰地表述具体操作 class Solution {pu…

基于GPU器件行为的创新分布式功能安全机制为智能驾驶保驾护航

作者&#xff1a;商瑞 陈娇 随着汽车智能化程度的快速提高&#xff0c;大量新的处理器和系统级芯片&#xff08;SoC&#xff09;被广泛引入到车辆中&#xff0c;无论是在驾驶还是座舱等场景&#xff0c;无论采用域控制器模式还是新兴的中央控制单元模式&#xff0c;都无一例外…

高美GULMAY高压发生器维修X射线源维修CF160

GULMAY高压发生器维修规格系列包括&#xff1a;CF,FC,CP等系列 维修类别&#xff1a;仪器仪表/无损检测仪器/其他无损检测仪器 GULMAY公司作为世界上X的工业X射线高压系统制造厂家之一,GULMAY公司拥有30多年的研发和制造经验,不但为XX射线探伤X域的用户提供种类繁多的标准型号…

动态规划-背包问题——[模版]完全背包问题

1.题目解析 题目来源 [模版]完全背包_牛客题霸_牛客 测试用例 2.算法原理 1.状态表示 与01背包相同&#xff0c;这里的完全背包也是需要一个二维dp表来表示最大价值&#xff0c;具体如下 求最大价值dp[i][j]:在[1,i]区间选择物品&#xff0c;此时总体积不大于j时的最大价值 求…

Android音视频直播低延迟探究之:WLAN低延迟模式

Android WLAN低延迟模式 Android WLAN低延迟模式是 Android 10 引入的一种功能&#xff0c;允许对延迟敏感的应用将 Wi-Fi 配置为低延迟模式&#xff0c;以减少网络延迟&#xff0c;启动条件如下&#xff1a; Wi-Fi 已启用且设备可以访问互联网。应用已创建并获得 Wi-Fi 锁&a…

Android setTheme设置透明主题无效

【问题现象】 1、首先&#xff0c;你在AndroidManifest.xml中声明一个activity&#xff0c;不给application或者activity设置android:theme, 例如这样&#xff1a; <applicationandroid:allowBackup"true"android:icon"mipmap/ic_launcher"android:lab…

基于Spring Boot的在线性格测试系统设计与实现(源码+定制+开发)智能性格测试与用户个性分析平台、在线心理测评系统的开发、性格测试与个性数据管理系统

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

摄像机视频分析软件下载LiteAIServer视频智能分析软件抖动检测的技术实现

在现代社会中&#xff0c;视频监控系统扮演着至关重要的角色&#xff0c;其可靠性和有效性在很大程度上取决于视频质量。然而&#xff0c;由于多种因素&#xff0c;如摄像机安装不当、外部环境振动或视频信号传输的不稳定&#xff0c;视频画面常常出现抖动问题&#xff0c;这不…

一文说清libc、glibc、glib的发展和关系

一 引言 在大家的技术生涯中&#xff0c;一定会遇到glib、glibc、libc这些个名词。 尤其像我这种对英文名脸盲的人&#xff0c;看着它们就头大&#xff0c;因为单从名字上看&#xff0c;也太像了&#xff0c;所以经常容易混淆。 即使翻翻网上的资料&#xff0c;看完还是有点懵…

【postman】怎么通过curl看请求报什么错

获取现成的curl方式&#xff1a; 1&#xff0c;拿别人给的curl 2&#xff0c;手机app界面通过charles抓包&#xff0c;点击接口复制curl 3&#xff0c;浏览器界面-开发者工具-选中接口复制curl 拿到curl之后打开postman&#xff0c;点击import&#xff0c;粘贴curl点击send&am…