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