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> 

运行结果:
Vue3中如何使用ref获取元素节点全面解析
注意点:
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> 

运行的结果:
Vue3中如何使用ref获取元素节点全面解析注意点:我们似乎没办法区分哪个 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> 

运行的结果:
Vue3中如何使用ref获取元素节点全面解析
这种形式既让我们的操作性变得更大,还解决了 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> 

运行的结果
Vue3中如何使用ref获取元素节点全面解析

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

运行的结果:
Vue3中如何使用ref获取元素节点全面解析