一篇文章搞懂Vue3中如何使用ref获取元素节点

 更新时间:2022年11月14日 09:27:41   作者:博客zhu虎康  
过去在Vue2中,我们采用ref来获取标签的信息,用以替代传统 js 中的 DOM 行为,下面这篇文章主要给大家介绍了关于如何通过一篇文章搞懂Vue3中如何使用ref获取元素节点的相关资料,需要的朋友可以参考下

前言

虽然在 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 使用方式有着较大的区别,但是它们的目的都是一样的,所以我们只要朝着目的前进,都会与美好相遇的!

到此这篇关于通过一篇文章搞懂Vue3中如何使用ref获取元素节点的文章就介绍到这了,更多相关Vue3用ref获取元素节点内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 浅谈Vue项目骨架屏注入实践

    浅谈Vue项目骨架屏注入实践

    这篇文章主要介绍了浅谈Vue项目骨架屏注入实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • vue vite之LogicFlow安装核心依赖及项目初始化详解

    vue vite之LogicFlow安装核心依赖及项目初始化详解

    这篇文章主要为大家介绍了vue vite之LogicFlow安装核心依赖及项目初始化详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • element-ui vue input输入框自动获取焦点聚焦方式

    element-ui vue input输入框自动获取焦点聚焦方式

    这篇文章主要介绍了element-ui vue input输入框自动获取焦点聚焦方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • vue项目Luckysheet的使用

    vue项目Luckysheet的使用

    这篇文章主要介绍了vue项目Luckysheet的使用,目前Luckysheet不支持使用npm安装包,所以只能使用CDN引入依赖,在vue项目的public/index.html文件里引入即可,本文通过示例代码给大家详细介绍,需要的朋友可以参考下
    2022-08-08
  • Vue新玩具VueUse的具体用法

    Vue新玩具VueUse的具体用法

    VueUse 是一个基于 Composition API 的实用函数集合。本文就详细的介绍了VueUse的具体用法,具有一定的参考价值,感兴趣的可以了解一下
    2021-11-11
  • 基于Vue技术实现递归组件的方法

    基于Vue技术实现递归组件的方法

    这篇文章主要为大家详细介绍了基于Vue技术实现递归组件的方法 ,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • 关于vue表单提交防双/多击的例子

    关于vue表单提交防双/多击的例子

    今天小编就为大家分享一篇关于vue表单提交防双/多击的例子,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-10-10
  • vue+swiper实现组件化开发的实例代码

    vue+swiper实现组件化开发的实例代码

    这篇文章主要介绍了vue+swiper实现组件化开发的相关资料,需要的朋友可以参考下
    2017-10-10
  • Vue编译优化实现流程详解

    Vue编译优化实现流程详解

    编译优化指的是编译器将模板编译为渲染函数的过程中,尽可能多的提取关键信息,并以此指导生成最优代码的过程,优化的方向主要是区分动态内容和静态内容,并针对不同的内容采用不同的优化策略
    2023-01-01
  • Vue中的el-date-picker时间选择器的使用实例详解

    Vue中的el-date-picker时间选择器的使用实例详解

    el-date-picker是Element UI框架中提供的日期选择器组件,它支持单个日期、日期范围、时间、日期时间等多种选择方式,本文给大家介绍Vue中的el-date-picker时间选择器的使用,感兴趣的朋友一起看看吧
    2023-10-10

最新评论