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-cli-service:command not found报错引发的实战案例
这篇文章主要给大家介绍了关于vue-cli-service:command not found报错引发的相关资料,文中通过实例代码将解决的过程介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下2023-02-02Vue3 openlayers加载瓦片地图并手动标记坐标点功能
这篇文章主要介绍了 Vue3 openlayers加载瓦片地图并手动标记坐标点功能,我们这里用vue/cli创建,我用的node版本是18.12.1,本文结合示例代码给大家介绍的非常详细,需要的朋友可以参考下2024-04-04
最新评论