Vue3如何在setup中獲取元素引用(ref)
Vue3在setup中獲取元素引用(ref)
在非setup鉤子中, 我們可以通過(guò)this.$refs來(lái)獲取指定元素,但是setup中沒(méi)有"this",所以要用其他方式來(lái)獲取元素。
一、關(guān)于ref關(guān)鍵字
在setup函數(shù)中,可以使用ref函數(shù),用于創(chuàng)建一個(gè)響應(yīng)式數(shù)據(jù),當(dāng)數(shù)據(jù)發(fā)生改變時(shí),Vue會(huì)自動(dòng)更新UI
一定要注意,ref創(chuàng)建的是一個(gè)響應(yīng)式數(shù)據(jù)。這個(gè)在VUE3.0中非常靈活,幾乎是怎么玩都行的。具體后邊還會(huì)說(shuō)到,這里大概說(shuō)一下基本用法。
1、引入ref
import { ref} from "vue";2、使用注意點(diǎn)
在 VUE 的模板中使用 ref 的值不需要通過(guò) value 獲取 (Vue 會(huì)通過(guò)自動(dòng)給 ref 的值加上 .value)
在 js 中使用 ref 的值必須使用 .value 獲取
二、在setup中引用元素
1、借助 ref() 函數(shù)
<template>
? ?<div ref="divRef" />
</template>
<script setup>
? import { ref } from 'vue'
? const divRef = ref(null)
? divRef.value
</script>2、找到 this
通過(guò) getCurrentInstance() 可以獲得 vue 實(shí)例對(duì)象
<template>
? ?<div ref="divRef" />
</template>
<script setup>
? import { getCurrentInstance, onMount } from 'vue'
? onMount(() => {
? ? getCurrentInstance().ctx.$refs.divRef
? })
</script>注意,使用 getCurrentInstance 是有一些限制的,可以參考官方說(shuō)明
3、使用 :ref
當(dāng)ref的值是一個(gè)函數(shù)的時(shí)候, 我們必須用":ref", 函數(shù)只有一個(gè)參數(shù), 那就是當(dāng)前元素
<template>
? ?<div :ref="getDivRef" />
</template>
<script setup>
? import { ref } from 'vue'
? let divRef = ref(null)
? const getDivRef = (el) => {
? ? divRef.value = el
? }
</script>Vue3使用ref獲取元素節(jié)點(diǎn)解析
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 訪問(wèn)元素
<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>運(yùn)行結(jié)果:

注意點(diǎn):
1.變量名稱(chēng)必須要與 ref 命名的屬性名稱(chēng)一致。
2.通過(guò) 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>運(yùn)行的結(jié)果:

注意點(diǎn):我們似乎沒(méi)辦法區(qū)分哪個(gè) li 標(biāo)簽?zāi)膫€(gè) ref,除此之外,我們的 itemRefs 數(shù)組不能夠保證與原數(shù)組順序相同,即與 list 原數(shù)組中的元素一一對(duì)應(yīng)。
:ref 綁定函數(shù)
ref 屬性接收的是一個(gè) setHelloRef 函數(shù),該函數(shù)會(huì)默認(rèn)接收一個(gè) el 參數(shù),這個(gè)參數(shù)就是我們需要獲取的 div 元素。假如需求中我們采用這種方式的話(huà),那么完全可以把 el 保存到一個(gè)變量中去,供后面使用。
<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>運(yùn)行的結(jié)果:

這種形式既讓我們的操作性變得更大,還解決了 v-for 循環(huán)是 ref 數(shù)組與原數(shù)組順序不對(duì)應(yīng)的問(wèn)題。
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) // 根據(jù)list數(shù)據(jù)中的id值 獲取對(duì)應(yīng)的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 組件實(shí)例
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>運(yùn)行的結(jié)果

childRef.value.message 為 undefined,這也是與 Vue2 的不同之處。在 Vue3 中,使用 ref 獲取子組件時(shí),如果想要獲取子組件的數(shù)據(jù)或者方法,子組件可以通過(guò)defineExpose 方法暴露數(shù)據(jù)。
改進(jìn)組件上使用 ref的寫(xiě)法
修改子組件代碼:
<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>父組件再次獲?。?/strong>
const childRef = ref<any>(null);
onMounted(() => {
console.log(childRef.value); // child 組件實(shí)例
console.log(childRef.value.message); // 我是子組件
childRef.value.onChange(); // 我是子組件方法
});運(yùn)行的結(jié)果:

總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用Vite+Vue3+TypeScript?搭建開(kāi)發(fā)腳手架的詳細(xì)過(guò)程
這篇文章主要介紹了Vite+Vue3+TypeScript?搭建開(kāi)發(fā)腳手架的詳細(xì)過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-02-02
vue+openlayer5獲取當(dāng)前鼠標(biāo)滑過(guò)的坐標(biāo)實(shí)現(xiàn)方法
在vue項(xiàng)目中怎么獲取當(dāng)前鼠標(biāo)劃過(guò)的坐標(biāo)呢?下面通過(guò)本文給大家分享實(shí)現(xiàn)步驟,感興趣的朋友跟隨小編一起看看吧2021-11-11
Vue reactive函數(shù)實(shí)現(xiàn)流程詳解
一個(gè)基本類(lèi)型的數(shù)據(jù),想要變成響應(yīng)式數(shù)據(jù),那么需要通過(guò)ref函數(shù)包裹,而如果是一個(gè)對(duì)象的話(huà),那么需要使用reactive函數(shù),這篇文章主要介紹了Vue reactive函數(shù)2023-01-01
完美解決通過(guò)IP地址訪問(wèn)VUE項(xiàng)目的問(wèn)題
這篇文章主要介紹了完美解決通過(guò)IP地址訪問(wèn)VUE項(xiàng)目的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
element validate驗(yàn)證函數(shù)不執(zhí)行的原因分析
這篇文章主要介紹了element validate驗(yàn)證函數(shù)不執(zhí)行的原因分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04
解決vue js IOS H5focus無(wú)法自動(dòng)彈出鍵盤(pán)的問(wèn)題
今天小編就為大家分享一篇解決vue js IOS H5focus無(wú)法自動(dòng)彈出鍵盤(pán)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
Vue彈窗的兩種實(shí)現(xiàn)方式實(shí)例詳解
這篇文章主要介紹了Vue彈窗的兩種實(shí)現(xiàn)方式,一種使用.sync修飾符另一種使用v-model,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08

