詳解vue2與vue3獲取模版引用ref的區(qū)別
雖然 Vue 的聲明性渲染模型為你抽象了大部分對(duì) DOM 的直接操作,但在某些情況下,我們?nèi)匀恍枰苯釉L問(wèn)底層 DOM 元素。要實(shí)現(xiàn)這一點(diǎn),我們可以使用特殊的 ref attribute:
ref 是一個(gè)特殊的 attribute,和 v-for 章節(jié)中提到的 key 類似。它允許我們?cè)谝粋€(gè)特定的 DOM 元素或子組件實(shí)例被掛載后,獲得對(duì)它的直接引用。這可能很有用,比如說(shuō)在組件掛載時(shí)將焦點(diǎn)設(shè)置到一個(gè) input 元素上,或在一個(gè)元素上初始化一個(gè)第三方庫(kù)。
Vue 2 中獲取模板引用
在Vue 2中,我們可以使用ref屬性來(lái)獲取模板中的DOM元素或組件實(shí)例的引用。這使得在Vue組件中訪問(wèn)和操作特定元素或組件變得非常方便。
獲取DOM元素引用
要獲取一個(gè)DOM元素的引用,我們可以在模板中使用ref屬性并為其指定一個(gè)名稱。然后,我們可以通過(guò)this.$refs來(lái)訪問(wèn)這個(gè)引用。
<template>
<div>
<button ref="myButton">點(diǎn)擊我</button>
</div>
</template>
<script>
export default {
mounted() {
// 在生命周期鉤子中使用$refs來(lái)獲取引用
this.$refs.myButton.innerText = '已點(diǎn)擊';
}
}
</script>在上面的例子中,我們給按鈕添加了一個(gè)ref屬性,值為myButton。然后在mounted生命周期鉤子中,我們使用this.$refs.myButton來(lái)獲取到這個(gè)按鈕的引用,并修改了它的文本內(nèi)容。
獲取組件引用
如果我們想獲取一個(gè)子組件的引用,也可以使用相同的ref屬性來(lái)實(shí)現(xiàn)。
<template>
<div>
<ChildComponent ref="myChildComponent" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
mounted() {
// 在生命周期鉤子中使用$refs來(lái)獲取子組件的引用
this.$refs.myChildComponent.someMethod();
}
}
</script>在上面的例子中,我們?cè)诟附M件中引入了一個(gè)名為ChildComponent的子組件,并在模板中使用了ref屬性來(lái)獲取它的引用。然后在mounted生命周期鉤子中,我們可以使用this.$refs.myChildComponent來(lái)訪問(wèn)并調(diào)用子組件的方法。
v-for 中的模板引用
當(dāng)在 v-for 中使用模板引用時(shí),相應(yīng)的引用中包含的值是一個(gè)數(shù)組
<script>
export default {
data() {
return {
list: [
/* ... */
]
}
},
mounted() {
console.log(this.$refs.items)
}
}
</script>
<template>
<ul>
<li v-for="item in list" ref="items">
{{ item }}
</li>
</ul>
</template>應(yīng)該注意的是,ref 數(shù)組并不保證與源數(shù)組相同的順序。
vue3 中獲取模板引用
訪問(wèn)模板引用
為了通過(guò)組合式 API 獲得該模板引用,我們需要聲明一個(gè)同名的 ref:
<script setup>
import { ref, onMounted } from 'vue'
// 聲明一個(gè) ref 來(lái)存放該元素的引用
// 必須和模板里的 ref 同名
const input = ref(null)
onMounted(() => {
input.value.focus()
})
</script>
<template>
<input ref="input" />
</template>如果不使用 <script setup>,需確保從 setup() 返回 ref:
export default {
setup() {
const input = ref(null)
// ...
return {
input
}
}
}注意,你只可以在組件掛載后才能訪問(wèn)模板引用。如果你想在模板中的表達(dá)式上訪問(wèn) input,在初次渲染時(shí)會(huì)是 null。這是因?yàn)樵诔醮武秩厩斑@個(gè)元素還不存在呢!
如果你需要偵聽(tīng)一個(gè)模板引用 ref 的變化,確??紤]到其值為 null 的情況:
watchEffect(() => {
if (input.value) {
input.value.focus()
} else {
// 此時(shí)還未掛載,或此元素已經(jīng)被卸載(例如通過(guò) v-if 控制)
}
})v-for 中的模板引用
當(dāng)在 v-for 中使用模板引用時(shí),對(duì)應(yīng)的 ref 中包含的值是一個(gè)數(shù)組,它將在元素被掛載后包含對(duì)應(yīng)整個(gè)列表的所有元素:
<script setup>
import { ref, onMounted } from 'vue'
const list = ref([
/* ... */
])
const itemRefs = ref([])
onMounted(() => console.log(itemRefs.value))
</script>
<template>
<ul>
<li v-for="item in list" ref="itemRefs">
{{ item }}
</li>
</ul>
</template>函數(shù)模板引用
除了使用字符串值作名字,ref attribute 還可以綁定為一個(gè)函數(shù),會(huì)在每次組件更新時(shí)都被調(diào)用。該函數(shù)會(huì)收到元素引用作為其第一個(gè)參數(shù):
<input :ref="(el) => { /* 將 el 賦值給一個(gè)數(shù)據(jù)屬性或 ref 變量 */ }">
注意我們這里需要使用動(dòng)態(tài)的 :ref 綁定才能夠傳入一個(gè)函數(shù)。當(dāng)綁定的元素被卸載時(shí),函數(shù)也會(huì)被調(diào)用一次,此時(shí)的 el 參數(shù)會(huì)是 null。你當(dāng)然也可以綁定一個(gè)組件方法而不是內(nèi)聯(lián)函數(shù)。
<div v-for=(item, index) in arrList>
<div :ref="el => myRefs[index]=el"></div>
</div>
setup(){
const myRefs = ref([]) as Ref<string[]>
return {
myRefs,
}
}組件上的 ref
模板引用也可以被用在一個(gè)子組件上。這種情況下引用中獲得的值是組件實(shí)例:
<script setup>
import { ref, onMounted } from 'vue'
import Child from './Child.vue'
const child = ref(null)
onMounted(() => {
// child.value 是 <Child /> 組件的實(shí)例
})
</script>
<template>
<Child ref="child" />
</template>如果一個(gè)子組件使用的是選項(xiàng)式 API 或沒(méi)有使用 <script setup>,被引用的組件實(shí)例和該子組件的 this 完全一致,這意味著父組件對(duì)子組件的每一個(gè)屬性和方法都有完全的訪問(wèn)權(quán)。這使得在父組件和子組件之間創(chuàng)建緊密耦合的實(shí)現(xiàn)細(xì)節(jié)變得很容易,當(dāng)然也因此,應(yīng)該只在絕對(duì)需要時(shí)才使用組件引用。大多數(shù)情況下,你應(yīng)該首先使用標(biāo)準(zhǔn)的 props 和 emit 接口來(lái)實(shí)現(xiàn)父子組件交互。
有一個(gè)例外的情況,使用了 <script setup> 的組件是默認(rèn)私有的:一個(gè)父組件無(wú)法訪問(wèn)到一個(gè)使用了 <script setup> 的子組件中的任何東西,除非子組件在其中通過(guò) defineExpose 宏顯式暴露:
<script setup>
import { ref } from 'vue'
const a = 1
const b = ref(2)
// 像 defineExpose 這樣的編譯器宏不需要導(dǎo)入
defineExpose({
a,
b
})
</script>當(dāng)父組件通過(guò)模板引用獲取到了該組件的實(shí)例時(shí),得到的實(shí)例類型為 { a: number, b: number } (ref 都會(huì)自動(dòng)解包,和一般的實(shí)例一樣)。
到此這篇關(guān)于詳解vue2與vue3獲取模版引用ref的區(qū)別的文章就介紹到這了,更多相關(guān)vue獲取ref內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue裝飾器中的vue-property-decorator?和?vux-class使用詳解
這篇文章主要介紹了Vue裝飾器中的vue-property-decorator?和?vux-class使用詳解,通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)vue-property-decorator?和?vux-class的使用感興趣的朋友一起看看吧2022-08-08
vite?+?electron-builder?打包配置詳解
這篇文章主要為大家介紹了electron基于vite?+?electron-builder?打包配置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
vue 使用rules對(duì)表單字段進(jìn)行校驗(yàn)的步驟
這篇文章主要介紹了vue 使用rules對(duì)表單字段進(jìn)行校驗(yàn)的步驟,幫助大家更好的理解和使用vue,感興趣的朋友可以了解下2020-12-12
Vue3整合WangEditor富文本編輯器的實(shí)踐指南
這篇文章主要為大家詳細(xì)介紹了如何在?Vue?3?項(xiàng)目中集成?WangEditor?富文本編輯器,實(shí)現(xiàn)圖文混排、自定義擴(kuò)展等高階功能,感興趣的小伙伴可以了解下2025-03-03
vue使用async/await來(lái)實(shí)現(xiàn)同步和異步的案例分享
近期項(xiàng)目中大量使用async,從服務(wù)器獲取數(shù)據(jù),解決一些并發(fā)傳參問(wèn)題,代碼很簡(jiǎn)單,在此也看了一些博客,現(xiàn)在async/await已經(jīng)大范圍讓使用,所以本文給大家介紹一下vue使用async/await來(lái)實(shí)現(xiàn)同步和異步的案例,需要的朋友可以參考下2024-01-01
vue鍵盤(pán)事件點(diǎn)擊事件加native操作
這篇文章主要介紹了vue鍵盤(pán)事件點(diǎn)擊事件加native操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
vue項(xiàng)目引入Iconfont圖標(biāo)庫(kù)的教程圖解
這篇文章主要介紹了vue項(xiàng)目引入Iconfont圖標(biāo)庫(kù)的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-10-10
在 Vue 項(xiàng)目中引入 tinymce 富文本編輯器的完整代碼
這篇文章主要介紹了在 Vue 項(xiàng)目中引入 tinymce 富文本編輯器的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-05-05

