Template Refs 模板參照是什麼東西啊?
我倒是很需要模板!希望可以重複使用啊~
不知道是不是這個東西?
雖然 Vue 的聲明式渲染模型為您抽象了大部分的直接 DOM 操作,但仍然可能有需要直接訪問底層 DOM 元素的情況。為了實現這一點,我們可以使用特殊的 ref
屬性:
<template>
<input ref="input">
</template>
ref
是一個特殊屬性,類似於在 v-for
章節中討論的 key
屬性。它允許我們在元素或子組件實例被掛載後獲得對特定 DOM 元素或子組件實例的直接參照。例如,在您需要在組件掛載時程序化地聚焦輸入框,或在元素上初始化第三方庫時非常有用。
使用 Composition API 獲取參照時,我們可以使用 useTemplateRef()
3.5+助手:
<script setup>
import { useTemplateRef, onMounted } from 'vue'
// 第一個參數必須與模板中的 ref 值匹配
const input = useTemplateRef('my-input')
onMounted(() => {
input.value.focus()
})
</script>
<template>
<input ref="my-input" />
</template>
使用 TypeScript 時,Vue 的 IDE 支援和 vue-tsc
會根據 ref
屬性使用的元素或組件,自動推斷 inputRef.value
的類型。
在 3.5 版本之前,useTemplateRef()
尚未引入,我們需要宣告一個名稱與模板 ref
屬性值匹配的 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
}
}
}
請注意,您只能在組件掛載後訪問參照。如果您嘗試在模板表達式中訪問 input
,它在第一次渲染時會是 null
。這是因為元素只有在第一次渲染後才存在!
如果您嘗試監視模板參照的變化,請確保考慮到參照值為 null
的情況:
watchEffect(() => {
if (input.value) {
input.value.focus()
} else {
// 還未掛載,或者元素被卸載(例如通過 v-if)
}
})
另請參見:模板參照的類型定义
v-for
中的參照 - Refs inside v-for需要 v3.2.25 或更高版本
當 ref
用於 v-for
時,對應的 ref
應該包含一個數組值,該數組在掛載後將填充元素:
<script setup>
import { ref, useTemplateRef, onMounted } from 'vue'
const list = ref([
/* ... */
])
const itemRefs = useTemplateRef('items')
onMounted(() => console.log(itemRefs.value))
</script>
<template>
<ul>
<li v-for="item in list" ref="items">
{{ item }}
</li>
</ul>
</template>
在 3.5 版本之前的使用情況
<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>
需要注意的是,ref 數組並不保證與源數組具有相同的順序。
除了使用字串鍵,ref
屬性也可以綁定到一個函數,該函數會在每次組件更新時被調用,並允許您完全靈活地選擇將元素引用存儲在何處。該函數會接收元素引用作為第一個參數:
<template>
<input :ref="(el) => { /* 將 el 指派給某個屬性或 ref */ }">
</template>
注意,我們使用了一個動態的 :ref
綁定,因此可以傳遞一個函數而不是 ref
名稱字串。當元素卸載時,參數將為 null
。當然,您也可以使用一個方法來代替內聯函數。
這部分假設您已經具備組件的相關知識。如果沒有,可以跳過,稍後再回來閱讀。
ref
也可以用在子組件上。在這種情況下,ref
將引用子組件實例:
<script setup>
import { useTemplateRef, onMounted } from 'vue'
import Child from './Child.vue'
const childRef = useTemplateRef('child')
onMounted(() => {
// childRef.value 將持有 <Child /> 的實例
})
</script>
<template>
<Child ref="child" />
</template>
3.5 之前的用法:
<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>
如果子組件使用 Options API 或沒有使用 <script setup>
,那麼引用的實例將與子組件的 this
相同,這意味著父組件可以完全訪問子組件的每個屬性和方法。這使得在父子組件之間創建緊密耦合的實現細節變得容易,因此應僅在絕對需要時使用組件 ref
。在大多數情況下,您應該首先嘗試使用標準的 props
和 emit
接口來實現父子交互。
這裡有一個例外:使用 <script setup>
的組件默認是私有的:父組件引用使用 <script setup>
的子組件時,無法訪問任何內容,除非子組件選擇使用 defineExpose
宏來暴露公共接口:
<script setup>
import { ref } from 'vue'
const a = 1
const b = ref(2)
// 編譯器宏(如 defineExpose)不需要被導入
defineExpose({
a,
b
})
</script>
當父組件通過模板 ref
獲得此組件的實例時,取回的實例將是 { a: number, b: number }
的形狀(ref
將自動解包,就像在正常實例上一樣)。
<template>
和 ref
在 Vue 中有著密切的關係,因為 ref
通常是在模板中使用來獲取對 DOM 元素或子組件實例的引用。這兩者的關係可以總結如下:
template
與 ref
的關係1. 定義模板結構:
<template>
標籤用來定義 Vue 組件的 HTML 結構,這是組件的視圖部分。2. 引用 DOM 元素:
ref
是一個特殊屬性,當應用於模板中的 DOM 元素時,Vue 會在組件掛載後將該元素的引用存儲到相應的變量中。<input ref="inputElement">
會讓你在組件邏輯中使用 this.$refs.inputElement
(或在 Composition API 中使用 ref
變量)來訪問該輸入框元素。3. 引用子組件:
ref
也可以用於子組件,允許你在父組件中直接訪問子組件實例及其方法和屬性。<ChildComponent ref="childComponent">
會讓你在父組件中使用 this.$refs.childComponent
來訪問子組件的實例。以下是一個簡單的示例,展示了如何在模板中使用 ref
來引用 DOM 元素和子組件:
<template>
<div>
<!-- 引用 DOM 元素 -->
<input ref="inputElement" placeholder="Type something" />
<!-- 引用子組件 -->
<ChildComponent ref="childComponent" />
</div>
</template>
<script>
import { ref, onMounted } from 'vue'
import ChildComponent from './ChildComponent.vue'
export default {
components: { ChildComponent },
setup() {
// 使用 ref 來保存 DOM 元素的引用
const inputElement = ref(null)
// 使用 ref 來保存子組件實例的引用
const childComponent = ref(null)
onMounted(() => {
// 可以在組件掛載後訪問這些引用
console.log(inputElement.value) // DOM 元素
console.log(childComponent.value) // 子組件實例
})
return {
inputElement,
childComponent
}
}
}
</script>
<template>
:用於定義組件的視圖結構,包括 HTML 和 Vue 指令。ref
:用於獲取模板中 DOM 元素或子組件實例引用,從而在組件邏輯中進行操作。透過在模板中使用 ref
屬性,你可以在 Vue 組件中輕鬆地訪問和操作具體的 DOM 元素或子組件,實現更靈活的交互和控制。
不知道是不是週末的關係?這邊怎麼看的霧濛濛www
太想放假了!各位週末愉快~
希望下次再來看這些文件會更熟一點www