一文搞懂Vue3中如何使用ref获取元素节点?
qiyuwang 2024-10-10 11:34 64 浏览 0 评论
前言
虽然在 Vue 中不提倡我们直接操作 DOM,毕竟 Vue 的理念是以数据驱动视图。但是在实际情况中,我们有很多需求都是需要直接操作 DOM 节点的,这个时候 Vue 提供了一种方式让我们可以获取 DOM 节点:ref 属性。ref 属性是 Vue2 和 Vue3 中都有的,但是使用方式却不大一样,这也导致了很多从 Vue2 转到 Vue3 的小伙伴感到有些困惑。
今天我们就来揭开 Vue3 中 ref 的神秘面纱!
1.回顾 Vue2 中的 ref
在学习 Vue3 中的 ref 之前,我们先来了解下 Vue2 中 ref,这样一对比,大家更能够加深印象,以及它们之间的区别。
获取节点:
这是 ref 的基本功能之一,目的就是获取元素节点,在 Vue 中使用方式也很简单,代码如下:
<template>
<div id="app">
<div ref="hello">小猪课堂</div>
</div>
</template>
<script>
export default {
mounted() {
console.log(this.$refs.hello); // <div>小猪课堂</div>
},
};
</script>
上段代码中可以看到我们在 div 元素上绑定了 ref 属性,并命名为 hello,接下来我们直接使用 this.$refs.hello 的方式就可以获取到该 DOM 元素了。
2.Vue3 中 ref 访问元素
Vue3 中通过 ref 访问元素节点与 Vue2 不太一样,在 Vue3 中我们是没有 this 的,所以当然也没有 this.$refs。想要获取 ref,我们只能通过声明变量的方式。
创建一个 Vite 项目:
为了方便演示,我们直接在 Vite 项目中演示 ref 代码,创建项目指令如下:
npm create vite@latest my-vue-app --template vue-ts
代码如下:
<template>
<div ref="hello">小猪课堂</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
const hello = ref<any>(null);
onMounted(() => {
console.log(hello.value); // <div>小猪课堂</div>
});
</script>
输出结果:
上段代码中我们同样给 div 元素添加了 ref 属性,为了获取到这个元素,我们声明了一个与 ref 属性名称相同的变量 hello,然后我们通过 hello.value 的形式便获取到了该 div 元素。
注意点:
- 变量名称必须要与 ref 命名的属性名称一致。
- 通过 hello.value 的形式获取 DOM 元素。
- 必须要在 DOM 渲染完成后才可以获取 hello.value,否则就是 null。
3.v-for 中使用 ref
使用 ref 的场景有多种,一种是单独绑定在某一个元素节点上,另一种便是绑定在 v-for 循环出来的元素上了。这是一种非常常见的需求,在 Vue2 中我们通常使用:ref="..."的形式,只要能够标识出每个 ref 不一样即可。
但是在 Vue3 中又不太一样,不过还是可以通过变量的形式接收。
代码如下:
<template>
<div ref="hello">小猪课堂</div>
<ul>
<li v-for="item in 10" ref="itemRefs">
{{item}} - 小猪课堂
</li>
</ul>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
const itemRefs = ref<any>([]);
onMounted(() => {
console.log(itemRefs.value);
});
</script>
输出结果:
上段代码中尽管是 v-for 循环,但是我们似乎使用 ref 的形式与第 2 节中的方式没有任何变化,我们同样使用变量的形式拿到了每一个 li 标签元素。
但是这里我们需要注意一下:我们似乎没办法区分哪个 li 标签哪个 ref,初次之外,我们的 itemRefs 数组不能够保证与原数组顺序相同,即与 list 原数组中的元素一一对应。
4.ref 绑定函数
前面我们在组件上定义 ref 时,都是以一个字符串的形式作为 ref 的名字,其实我们的 ref 属性还可以接收一个函数作为属性值,这个时候我们需要在 ref 前面加上:。
代码如下:
<template>
<div :ref="setHelloRef">小猪课堂</div>
</template>
<script setup lang="ts">
import { ComponentPublicInstance, HTMLAttributes } from "vue";
const setHelloRef = (el: HTMLElement | ComponentPublicInstance | HTMLAttributes) => {
console.log(el); // <div>小猪课堂</div>
};
</script>
输出结果:
上段代码中 ref 属性接收的是一个 setHelloRef 函数,该函数会默认接收一个 el 参数,这个参数就是我们需要获取的 div 元素。假如需求中我们采用这种方式的话,那么完全可以把 el 保存到一个变量中去,供后面使用。
那么,我们在 v-for 中是否也能采用这种方式呢?
答案是可以的!
v-for 中使用
代码如下:
<template>
<ul>
<li v-for="item in 10" :ref="(el) => setItemRefs(el, item)">
{{ item }} - 小猪课堂
</li>
</ul>
</template>
<script setup lang="ts">
import { ComponentPublicInstance, HTMLAttributes, onMounted } from "vue";
let itemRefs: Array<any> = [];
const setItemRefs = (el: HTMLElement | ComponentPublicInstance | HTMLAttributes, item:number) => {
if(el) {
itemRefs.push({
id: item,
el,
});
}
}
onMounted(() => {
console.log(itemRefs);
});
</script>
输出结果:
在 v-for 中使用函数的形式传入 ref 与不使用 v-for 时的形式差不多,不过这里我们做了一点变通,为了区别出哪个 ref 是哪一个 li 标签,我们决定将 item 传入函数,也就是(el) => setItemRefs(el, item)的写法。
这种形式的好处既让我们的操作性变得更大,还解决了 v-for 循环是 ref 数组与原数组顺序不对应的问题。
5.组件上使用 ref
前面我们所使用 ref 时,都是在一个具体的 dom 元素上绑定,但是我们也可以将 ref 绑定在组件上,比如在 Vue2 中,我们将 ref 绑定在组件上时,便可以获取到该组件里面的所有数据和方法.
虽然 Vue3 中也可以将 ref 绑定在组件上,但是具体能获取组件的哪些值还是有一些区别的,我们一起来看看。
代码如下:
<template>
<child ref="childRef"></child>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import child from "./child.vue";
const childRef = ref<any>(null);
onMounted(() => {
console.log(childRef.value); // child 组件实例
console.log(childRef.value.message); // undefined
});
</script>
子组件 child 代码:
<template>
<div>{{ message }}</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
const message = ref<string>("我是子组件");
const onChange = () => {};
</script>
输出结果:
上段代码中我们新增了一个子组件,然后再子组件上面绑定了 ref,其用法基本上和 ref 直接绑定在 DOM 元素上一致。
但是如果我们把 ref 绑定再组件上,通常就是为了调用子组件里面的方法或者数据,可是从上面的输出结果来看,我们没有获取到数据,即 childRef.value.message 为 undefined,这也是与 Vue2 的不同之处。
在 Vue3 中,使用 ref 获取子组件时,如果想要获取子组件的数据或者方法,子组件可以通过
defineExpose 方法暴露数据。
修改子组件代码:
<template>
<div>{{ message }}</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
const message = ref<string>("我是子组件");
const onChange = () => {
console.log("我是子组件方法")
};
defineExpose({
message,
onChange
});
</script>
父组件再次获取:
const childRef = ref<any>(null);
onMounted(() => {
console.log(childRef.value); // child 组件实例
console.log(childRef.value.message); // 我是子组件
childRef.value.onChange(); // 我是子组件方法
});
输出结果:
可以看到我们在父组件中可以获取到子组件暴露的数据和方法了。
总结
虽然 Vue2 和 Vue3 中的 ref 使用方式有着较大的区别,但是它们的目的都是一样的,所以我们只要朝着目的前进,都会与美好相遇的!
相关推荐
- # 安装打开 ubuntu-22.04.3-LTS 报错 解决方案
-
#安装打开ubuntu-22.04.3-LTS报错解决方案WslRegisterDistributionfailedwitherror:0x800701bcError:0x80070...
- 利用阿里云镜像在ubuntu上安装Docker
-
简介:...
- 如何将Ubuntu Kylin(优麒麟)19.10系统升级到20.04版本
-
UbuntuKylin系统使用一段时间后,有新的版本发布,如何将现有的UbuntuKylin系统升级到最新版本?可以通过下面的方法进行升级。1.先查看相关的UbuntuKylin系统版本情况。使...
- Ubuntu 16.10内部代号确认为Yakkety Yak
-
在正式宣布Ubuntu16.04LTS(XenialXerus)的当天,Canonical创始人MarkShuttleworth还非常开心的在个人微博上宣布Ubuntu下个版本16.10的内...
- 如何在win11的wsl上装ubuntu(怎么在windows上安装ubuntu)
-
在Windows11的WSL(WindowsSubsystemforLinux)上安装Ubuntu非常简单。以下是详细的步骤:---...
- Win11学院:如何在Windows 11上使用WSL安装Ubuntu
-
IT之家2月18日消息,科技媒体pureinfotech昨日(2月17日)发布博文,介绍了3中简便的方法,让你轻松在Windows11系统中,使用WindowsSubs...
- 如何查看Linux的IP地址(如何查看Linux的ip地址)
-
本头条号每天坚持更新原创干货技术文章,欢迎关注本头条号"Linux学习教程",公众号名称“Linux入门学习教程"。...
- 怎么看电脑系统?(怎么看电脑系统配置)
-
要查看电脑的操作系统信息,可以按照以下步骤操作,根据不同的操作系统选择对应的方法:一、Windows系统通过系统属性查看右键点击桌面上的“此电脑”(或“我的电脑”)图标,选择“属性”。在打开的...
- 如何查询 Linux 内核版本?这些命令一定要会!
-
Linux内核是操作系统的核心,负责管理硬件资源、调度进程、处理系统调用等关键任务。不同的内核版本可能支持不同的硬件特性、提供新的功能,或者修复了已知的安全漏洞。以下是查询内核版本的几个常见场景:...
- 深度剖析:Linux下查看系统版本与CPU架构
-
在Linux系统管理、维护以及软件部署的过程中,精准掌握系统版本和CPU架构是极为关键的基础操作。这些信息不仅有助于我们深入了解系统特性、判断软件兼容性,还能为后续的软件安装、性能优化提供重要依据。接...
- 504 错误代码解析与应对策略(504错误咋解决)
-
在互联网的使用过程中,用户偶尔会遭遇各种错误提示,其中504错误代码是较为常见的一种。504错误并非意味着网站被屏蔽,它实际上是指服务器在规定时间内未能从上游服务器获取响应,专业术语称为“Ga...
- 猎聘APP和官网崩了?回应:正对部分职位整改,临时域名可登录
-
10月12日,有网友反映猎聘网无法打开,猎聘APP无法登录。截至10月14日,仍有网友不断向猎聘官方微博下反映该情况,而猎聘官方微博未发布相关情况说明,只是在微博内对反映该情况的用户进行回复,“抱歉,...
- 域名解析的原理是什么?域名解析的流程是怎样的?
-
域名解析是网站正常运行的关键因素,因此网站管理者了解域名解析的原理和流程对于做好域名管理、解决常见解析问题,保障网站的正常运转十分必要。那么域名解析的原理是什么?域名解析的流程是怎样的?接下来,中科三...
- Linux无法解析域名的解决办法(linux 不能解析域名)
-
如果由于误操作,删除了系统原有的dhcp相关设置就无法正常解析域名。 此时,需要手动修改配置文件: /etc/resolv.conf 将域名解析服务器手动添加到配置文件中 该文件是DNS域名解...
- 域名劫持是什么?(域名劫持是什么)
-
域名劫持是互联网攻击的一种方式,通过攻击域名解析服务器(DNS),或伪造域名解析服务器(DNS)的方法,把目标网站域名解析到错误的地址从而实现用户无法访问目标网站的目的。说的直白些,域名劫持,就是把互...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- # 安装打开 ubuntu-22.04.3-LTS 报错 解决方案
- 利用阿里云镜像在ubuntu上安装Docker
- 如何将Ubuntu Kylin(优麒麟)19.10系统升级到20.04版本
- Ubuntu 16.10内部代号确认为Yakkety Yak
- 如何在win11的wsl上装ubuntu(怎么在windows上安装ubuntu)
- Win11学院:如何在Windows 11上使用WSL安装Ubuntu
- 如何查看Linux的IP地址(如何查看Linux的ip地址)
- 怎么看电脑系统?(怎么看电脑系统配置)
- 如何查询 Linux 内核版本?这些命令一定要会!
- 深度剖析:Linux下查看系统版本与CPU架构
- 标签列表
-
- navicat无法连接mysql服务器 (65)
- 下横线怎么打 (71)
- flash插件怎么安装 (60)
- lol体验服怎么进 (66)
- ae插件怎么安装 (62)
- yum卸载 (75)
- .key文件 (63)
- cad一打开就致命错误是怎么回事 (61)
- rpm文件怎么安装 (66)
- linux取消挂载 (81)
- ie代理配置错误 (61)
- ajax error (67)
- centos7 重启网络 (67)
- centos6下载 (58)
- mysql 外网访问权限 (69)
- centos查看内核版本 (61)
- ps错误16 (66)
- nodejs读取json文件 (64)
- centos7 1810 (59)
- 加载com加载项时运行错误 (67)
- php打乱数组顺序 (68)
- cad安装失败怎么解决 (58)
- 因文件头错误而不能打开怎么解决 (68)
- js判断字符串为空 (62)
- centos查看端口 (64)