【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.mzph.cn/news/885801.shtml

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

相关文章

HTB:Photobomb[WriteUP]

目录 连接至HTB服务器并启动靶机 使用nmap对靶机进行端口开放扫描 再次使用nmap对靶机开放端口进行脚本、服务扫描 使用ffuf进行简单的子域名扫描 使用浏览器直接访问该域名 选取一个照片进行下载&#xff0c;使用Yakit进行抓包 USER_FLAG&#xff1a;a9afd9220ae2b5731…

蓝桥杯c++算法学习【1】之枚举与模拟(卡片、回文日期、赢球票、既约分数:::非常典型的比刷例题!!!)

别忘了请点个赞收藏关注支持一下博主喵&#xff01;&#xff01;&#xff01; 关注博主&#xff0c;更多蓝桥杯nice题目静待更新:) 枚举与模拟 一、卡片&#xff1a; 【问题描述】 小蓝有很多数字卡片&#xff0c;每张卡片上都是一个数字&#xff08;0到9&#xff09;。 小蓝…

html页面中的内容替换,或改变某些字的颜色

1. html页面中的内容替换,或改变某些字的颜色 前端使用innnerHtml显示返回值+innerHtml文字显示两种不同的颜色(两部分显示颜色不一样) 1.1. html字符串改变某些字的颜色 需求:要文本框的字体部分改变颜色、大小、换行等功能。在了解需求后,文本框input发现完全满足不了现需…

Linux——简单认识vim、gcc以及make/Makefile

前言&#xff1a;大佬写博客给别人看&#xff0c;菜鸟写博客给自己看&#xff0c;我是菜鸟。 1、vim操作&#xff1a; 默认打开vim时&#xff0c;vim处于命令模式。(在其他模式中&#xff0c;Esc就能够返回命令模式) 常用的命令有&#xff1a; n gg&#xff1a;跳转到n行&…

C++基础(12.红黑树实现)

目录 红黑树的概念&#xff1a; 红黑树规则&#xff1a; 红黑树如何确保最长路径不超过最短路径的2倍的&#xff1f; 红黑树的效率&#xff1a; 红黑树的插入: 红黑树树插入⼀个值的大概过程: 情况1&#xff1a;变色 情况2&#xff1a;单旋变色&#xff1a; 情况3&…

Spark 的容错机制:保障数据处理的稳定性与高效性

Spark 的介绍与搭建&#xff1a;从理论到实践_spark环境搭建-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交&#xff1a;本地与集群模式全解析-CSDN博客 Spark on YARN&#xff1a;Spark集群模式…

Linux内核编程(二十)RTC子系统一驱动rx8010

本文目录 一、基础知识点1.什么是RTC&#xff1f;2. RTC方案3. 电路原理图 二、RTC芯片&#xff08;RX8010&#xff09;移植三、关于时间的一些命令四、应用层使用1. 使用RTC驱动2. 使用time.h库&#xff08;额外知识点&#xff09; 一、基础知识点 1.什么是RTC&#xff1f; R…

GESP4级考试语法知识(贪心算法(一))

海盗船代码&#xff1a; #include<iostream> #include<algorithm> using namespace std; int data[21]; int main() {int n;cin>>n;for(int i0;i<n;i)cin>>data[i];sort(data,datan);int temp0,sum0;for(int i0;i<n;i){tempdata[i];if(temp>…

036 RabbitMQ消息确认 死信队列 延时队列

文章目录 生产者确认模式application.propertiesMessageController.javaMessageConfirmRallback.java 生产者回退模式application.propertiesMessageConfirmRallback.javaMessageController.java 消费者手动确认application.propertiesConsumerAckQueueListener.java 死信队列延…

Unity 插件 - Project窗口资源大小显示

Unity 插件 - Project窗口资源大小显示 &#x1f354;功能&#x1f32d;安装 &#x1f354;功能 &#x1f4a1;.显示Project Assets 和Packages下所有文件的大小&#xff08;右侧显示&#xff09; &#x1f4a1;.统计选中文件夹及其子文件夹下所有文件的大小并显示&#xff08…

Maven 中央仓库地址 mvnrepository.com

下载一些 jar 包驱动&#xff0c;不需用去官网下了&#xff0c;直接去 Maven 中央仓库&#xff0c;高效、简单 Maven 中央仓库地址 https://mvnrepository.com/open-source 我们下期见&#xff0c;拜拜&#xff01;

制作自己的刷题小题库,提高刷题效率

日常刷题 乱序/背题多种模式 组队刷题 查看小组的刷题统计 在线考试 创建考试多人同时答题 ----这是一条分割线----- 土著刷题&#xff0c;是一款可以导入题库的在线刷题学习小&#x1f34a;序&#xff0c;提供一套以【搭建题库-组建小组-刷题练习-在线考试】为中心的完整服务…

WPF在MVVM模式下怎么实现导航功能

在mvvm的模式下wpf通过frame实现页面跳转_哔哩哔哩_bilibili 视频讲解同步可观看 如下图&#xff0c;我们要实现点击左侧的菜单&#xff0c;在右侧展示不同的页面 实现代码如下&#xff1a; 一、如何从主窗体跳转到页面。 1、在mainwindow.xaml的菜单栏代码里加入如下代码 …

VSCode中python插件安装后无法调试

问题 VSCode中python插件安装后无法调试&#xff0c;如下&#xff0c;点击调试&#xff0c;VScode中不报错&#xff0c;也没有调试 解决方法 1、查看配置 打开所在路径 2、拷贝 将整个文件夹拷贝到vscode默认路径下 3、问题解决 再次调试&#xff0c;可以正常使用了…

光模块基础知识

1. 光模块的封装 光模块是光收发模块的简称&#xff0c;主要根据不同的外型来区分&#xff0c;而在同一外型中&#xff0c;又有着多种规格&#xff1b;在数据通信领域&#xff0c;最常见的光模块&#xff08;根据外型区分&#xff09;分别是SFF、GBIC、SFP、和XFP、QSFP 、XEN…

【GPTs】MJ Prompt Creator:轻松生成创意Midjourney提示词

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | GPTs应用实例 文章目录 &#x1f4af;GPTs指令&#x1f4af;前言&#x1f4af;MJ Prompt Creator主要功能适用场景优点缺点 &#x1f4af; 小结 &#x1f4af;GPTs指令 中文翻译&#xff1a; 任务说明 您是一款为幻灯片工…

uniapp路由与页面跳转详解:API调用与Navigator组件实战

UniApp路由与页面跳转详解&#xff1a;API调用与Navigator组件实战 路由 uniapp页面路由为框架统一管理&#xff0c;开发者需要在page.json里面配置每个路由页面的路径及页面样式。 路由跳转 uniapp有两种页面路由跳转方式&#xff0c;调用API跳转和navigator组件跳转。 调…

机器学习 笔记

特征值提取 字典 from sklearn.extaction import DictVectorizer mDictVectorizer(sparseFalse)#sparse是否转换成三元组形式 data[], #传入字典数据 data1model.fit_transform(data) #使用API 英文特征值提取 from sklearn.feature_extraction.text import CountVe…

【智谱开放平台-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

如何搭建自动化测试框架

软件测试资料领取&#xff1a;[内部资源] 想拿年薪40W的软件测试人员&#xff0c;这份资料必须领取~ 软件测试面试刷题工具&#xff1a;软件测试面试刷题【800道面试题答案免费刷】 关于测试框架的好处&#xff0c;比如快速回归提高测试效率&#xff0c;提高测试覆盖率等这里…