【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.xdnf.cn/news/12801.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Linux磁盘分区

文章目录 磁盘分区 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Linux专栏&#xff1a;点击 ⏰️创作时间&#xff1a;2024年11月12日13点20分 磁盘分区 MBR 主启动记录分区方案指定了运行BIOS固件的系统上应如何对磁盘进行分区&#xff0c;存在与驱动开…

2. Spring Cloud 微服务基础环境搭建

2. Spring Cloud 微服务基础环境搭建 文章目录 2. Spring Cloud 微服务基础环境搭建前言1. 微服务需求解析2. 具体搭建微服务步骤&#xff1a;2.1 创建父工程 &#xff0c;用于聚合其它微服务模块2.1.1 需求说明/图解2.1.2 具体实现步骤2.1.3 注意事项和具体细节 2.2 创建会员中…

微信朋友圈营销

朋友圈营销4567法则

【赵渝强老师】MySQL InnoDB的表空间

InnoDB存储引擎目前是MySQL默认的存储引擎&#xff0c;它主要由三部分组成&#xff0c;分别是&#xff1a;存储结构、内存结构和线程结构。InnoDB的存储结构又可以分为逻辑存储结构和物理存储结构。InnoDB存储引擎的逻辑存储结构和Oracle大致相同&#xff0c;所有数据都被逻辑地…

docker安装redis

1、拉取镜像 docker pull redis:latest运行之前需要再/data/redis创建redis.conf配置文件 内容如下 # bind 192.168.1.100 10.0.0.1 # bind 127.0.0.1 ::1 #bind 127.0.0.1protected-mode noport 6379tcp-backlog 511requirepass roottimeout 0tcp-keepalive 300daemonize no…

vue项目多入口文件。vue.config.js如何修改配置

我们知道vue项目是单入口。指定一个入口文件去加载他所有的依赖。如果我们希望他有多个入口文件怎么办呢&#xff1f; 我们可以在public下面新建一个html的文件 然后src下新增一个文件夹&#xff0c;用来放APP.vue和 main.js。 然后修改vue.config.js。把他的pages改成2个入…

NCC前端调用查询弹框

系统自带的查询模板 弹框 调启使用默认的 查询模板 是在 单据模板的 列表模板中&#xff0c;有个查询区域 &#xff0c;查询区域就是查询模板内容如果在列表页做客开 新增按钮 调启查询模板 无问题&#xff0c;但是目前需求是需要再卡片页面下调启系统标准的调启模板代码 //调…

SpringBoot中的注解详解(二)

四、Param() &#xff08;mapper包 Dao层&#xff09; Param()&#xff1a; 功能&#xff1a; 用于在Mapper接口的方法参数上标记参数名称&#xff0c;以便在SQL语句中引用这些参数。 参数命名&#xff1a;在Mapper接口的方法参数上使用Param注解&#xff0c;可以为参数指定一…

一文1800字使用Jmeter进行http接口性能测试!

接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及系统间的相互逻辑依赖关系等。 为什么要做接口测试&#xff1f; 越底层发现b…

新版flask pin码计算

Python debug pin码计算 需开启debug from flask import Flask app Flask(__name__) app.route("/") def index():return "Hello World" app.run(debugTrue) /console路由填入上方控制台的 PIN 码即可执行 Python 命令 Flask 的 PIN 码计算仅与 werkze…

比 PyTorch 更快的嵌入Python库:FastEmbed

嵌入生成 已成为自然语言处理&#xff08;NLP&#xff09;中不可或缺的一部分。 无论是智能推荐、文本相似度计算&#xff0c;还是聊天机器人&#xff0c;嵌入技术都扮演着重要角色。然而&#xff0c;我们常常会陷入繁重的库和庞大的模型中&#xff0c;耗时费力。 今天&#…

大模型部署解决方案之TorchServe+vLLM

TorchServe 是PyTorch 中将模型部署到生产环境的一个解决方案。它用HTTP 或HTTPS API 封装模型&#xff0c;可以处理多种任务&#xff0c;包括为部署模型分配workers、负责客户端和服务器之间通信等。 10月份发布的TorchServe 0.12 增加了对GenAI的支持&#xff0c;简化了大语…

博弈论(零和博弈)英文版题解

翻译&#xff1a; 假设我们有一个两人零和游戏&#xff0c;每个玩家有两种行动&#xff0c;行收益矩阵如下&#xff1a; 计算行和列玩家的最小最大最优策略以及游戏的价值。 X Y A a11 a12 B a21 a22 选项&#xff1a; 1. 行玩家&#x…

虚拟现实辅助工程技术应用于员工培训

你还在使用传统的入职方法吗&#xff0c;比如印刷指南、演示、课堂培训、讲座等等&#xff1f;是时候改变了。虚拟现实辅助工程技术提供了一个机会&#xff0c;可以让新员工的入职过程更高效、更有趣&#xff0c;也更令人兴奋。想象一下这样一个场景&#xff0c;新员工可以在第…

【健康警钟】胆已切除,生活调理有“胆”更精彩!必看指南!

在现代社会&#xff0c;由于生活习惯、饮食习惯等多种因素&#xff0c;一些人可能不得不面对胆囊切除手术。虽然手术能够有效解决胆囊结石、胆囊炎等问题&#xff0c;但胆囊作为人体的一部分&#xff0c;其功能的丧失无疑会对生活带来一定影响。那么&#xff0c;胆被割了之后&a…

windows NGIMX配置WebSocket反向代理

linux下 据说nginx是要有 stream的模块 Linux安装Nginx步骤之后续&#xff0c;带stream模块-CSDN博客 Nginx从1.3.13版本就开始支持WebSocket linux 下参考如下链接 配置 Nginx 反向代理 WebSocket - 哈喽哈喽111111 - 博客园 (cnblogs.com) SSL的配置参考 【Linux】采用…

三种读取配置文件的方式

在编写JDBC的util包以读取文件时&#xff0c;配置文件的位置会影响其读取方式。当前&#xff0c;默认配置文件直接放置在src文件夹下。 当读取.properties文件代码写法为&#xff1a; Properties props new Properties(); props.load(new FileInputStream("db.propertie…

丹摩征文活动|CogVideoX-2b:从安装到上线,轻松搞定全过程!

CogVideoX-2b&#xff1a;从安装到上线&#xff0c;轻松搞定全过程&#xff01; CogVideoX简介 CogVideoX的推出标志着视频生成技术的一次重大突破。过去&#xff0c;如何在保持高效的同时提升视频质量一直是一个难题&#xff0c;但CogVideoX 通过其先进的3D变分自编码器&…

工位管理优化:Spring Boot企业级系统

3系统分析 3.1可行性分析 通过对本企业级工位管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本企业级工位管理系统采用SSM框架&#xff0c;JAVA作为开…

EMQX服务器的搭建,实现本地机和虚拟机之间的MQTT通信(详细教程)

前言 MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的&#xff0c;这些特点使它适用范围非常广泛。 MQTT协议中有三种身份&#xff1a;发布者&#xff08;Publish&#xff09;、代理&#xff08;Broker&#xff09;&#xff08;…