Vue3如何在setup中获取元素引用(ref)

 更新时间:2023年07月06日 10:05:03   作者:不怕麻烦的鹿丸  
这篇文章主要介绍了Vue3如何在setup中获取元素引用(ref)问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

Vue3在setup中获取元素引用(ref)

在非setup钩子中, 我们可以通过this.$refs来获取指定元素,但是setup中没有"this",所以要用其他方式来获取元素。

一、关于ref关键字

在setup函数中,可以使用ref函数,用于创建一个响应式数据,当数据发生改变时,Vue会自动更新UI

一定要注意,ref创建的是一个响应式数据。这个在VUE3.0中非常灵活,几乎是怎么玩都行的。具体后边还会说到,这里大概说一下基本用法。

1、引入ref

import { ref} from "vue";

2、使用注意点

在 VUE 的模板中使用 ref 的值不需要通过 value 获取 (Vue 会通过自动给 ref 的值加上 .value)

在 js 中使用 ref 的值必须使用 .value 获取

二、在setup中引用元素

1、借助 ref() 函数

<template>
   <div ref="divRef" />
</template>
<script setup>
  import { ref } from 'vue'
  const divRef = ref(null)
  divRef.value
</script>

2、找到 this

通过 getCurrentInstance() 可以获得 vue 实例对象

<template>
   <div ref="divRef" />
</template>
<script setup>
  import { getCurrentInstance, onMount } from 'vue'
  onMount(() => {
    getCurrentInstance().ctx.$refs.divRef
  })
</script>

注意,使用 getCurrentInstance 是有一些限制的,可以参考官方说明

3、使用 :ref 

当ref的值是一个函数的时候, 我们必须用":ref", 函数只有一个参数, 那就是当前元素

<template>
   <div :ref="getDivRef" />
</template>
<script setup>
  import { ref } from 'vue'
  let divRef = ref(null)
  const getDivRef = (el) => {
    divRef.value = el
  }
</script>

Vue3使用ref获取元素节点解析

Vue2 中的 ref

<template>
  <div id="app">
    <div ref="hello">小猪课堂</div>
  </div>
</template>
<script>
export default {
  mounted() {
    console.log(this.$refs.hello); // <div>小猪课堂</div>
  },
};
</script>

Vue3 中 ref 访问元素

<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>

运行结果:

在这里插入图片描述

注意点:

1.变量名称必须要与 ref 命名的属性名称一致。

2.通过 hello.value 的形式获取 DOM 元素。

3.必须要在 DOM 渲染完成后才可以获取 hello.value,否则就是 null。

v-for 中使用 ref

<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>

运行的结果:

在这里插入图片描述

注意点:我们似乎没办法区分哪个 li 标签哪个 ref,除此之外,我们的 itemRefs 数组不能够保证与原数组顺序相同,即与 list 原数组中的元素一一对应。

:ref 绑定函数

ref 属性接收的是一个 setHelloRef 函数,该函数会默认接收一个 el 参数,这个参数就是我们需要获取的 div 元素。假如需求中我们采用这种方式的话,那么完全可以把 el 保存到一个变量中去,供后面使用。

<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>

v-for的更改后使用:方法1

<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的更改后使用:方法2

<template>
   <div ref='getDivDom' v-for="item in list" :data-id="item.id"></div> 
</template>
<script setup>
import { ref} from 'vue'
const divDomList = ref(new Map());
const getDivDom = el=>{
    if(el){
        divDomList.set(el.dataset['id'],el) 
    }
}
// const el =divDomList.get(id) // 根据list数据中的id值 获取对应的dom元素 

组件上使用 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>
<template>
  <div>{{ message }}</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
const message = ref<string>("我是子组件");
const onChange = () => {};
</script>

运行的结果

在这里插入图片描述

childRef.value.message 为 undefined,这也是与 Vue2 的不同之处。在 Vue3 中,使用 ref 获取子组件时,如果想要获取子组件的数据或者方法,子组件可以通过defineExpose 方法暴露数据。

改进组件上使用 ref的写法

修改子组件代码:

<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(); // 我是子组件方法
});

运行的结果:

在这里插入图片描述

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • vue实现大文件切片上传的示例详解

    vue实现大文件切片上传的示例详解

    前端上传文件很大时,会出现各种问题,比如连接超时了,网断了,都会导致上传失败,这个时候就需要将文件切片上传,下面我们就来学习一下如何使用vue实现大文件切片上传吧
    2023-11-11
  • Vue中虚拟列表的原理与实现详解

    Vue中虚拟列表的原理与实现详解

    虚拟列表是一种技术,它只渲染用户当前可见的列表项,而不是渲染整个列表,这篇文章主要来和大家聊聊虚拟列表的原理与实现,希望对大家有所帮助
    2023-05-05
  • Vue拖拽组件列表实现动态页面配置功能

    Vue拖拽组件列表实现动态页面配置功能

    这篇文章主要介绍了Vue拖拽组件列表实现动态页面配置功能,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-06-06
  • Vue完整版和runtime版的区别详解

    Vue完整版和runtime版的区别详解

    这篇文章主要为大家介绍了Vue完整版和runtime版的区别详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • 关于引入vue.js 文件的知识点总结

    关于引入vue.js 文件的知识点总结

    在本篇文章里小编给大家分享的是关于引入vue.js 文件的知识点总结,有需要的朋友们可以参考学习下。
    2020-01-01
  • vue中内网/局域网/离线的情况下使用及建立项目方式

    vue中内网/局域网/离线的情况下使用及建立项目方式

    这篇文章主要介绍了vue中内网/局域网/离线的情况下使用及建立项目方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • vue3.0手动封装分页组件的方法

    vue3.0手动封装分页组件的方法

    这篇文章主要为大家详细介绍了vue3.0手动封装分页组件的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • Vue执行方法,方法获取data值,设置data值,方法传值操作

    Vue执行方法,方法获取data值,设置data值,方法传值操作

    这篇文章主要介绍了Vue执行方法,方法获取data值,设置data值,方法传值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • vue echarts实现横向柱状图

    vue echarts实现横向柱状图

    这篇文章主要为大家详细介绍了vue echarts实现横向柱状图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • vue中组件传参的几种常用方法举例

    vue中组件传参的几种常用方法举例

    这篇文章主要给大家介绍了关于vue中组件传参的几种常用方法,Vue组件传参方也是面试最常考的内容,文中通过代码实例介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08

最新评论