Vue 3 中的模板引用允许开发者在模板中通过 ref 关键字创建一个对元素或组件实例的可复用引用。该引用可以在 JavaScript 逻辑中直接操作,从而访问对应的 DOM 元素或组件实例,实现对组件内部状态的精细控制和交互处理。
模板引用的核心规则:脚本中声明的 ref 变量名,必须与模板中 ref 属性值完全一致;DOM 元素仅在组件挂载完成后,才能通过 .value 访问。
<script setup>
import { ref, onMounted } from 'vue'
// 声明 ref 接收 DOM 引用,初始值为 null
const input = ref(null)
// 组件挂载后,DOM 渲染完成,才可访问元素
onMounted(() => {
// 访问原生 DOM 元素
input.value.focus()
})
</script>
<template>
<!-- 绑定模板引用,名称与脚本变量一致 -->
<input ref="input" />
</template>模板部分 通过 ref="input" 为 input 元素绑定引用标识,Vue 会自动将该 DOM 元素赋值给同名的响应式变量。
脚本部分
导入 ref 创建响应式引用,onMounted 保证 DOM 渲染完成;
初始值 null:挂载前模板引用默认指向 null,不可提前访问;
input.value:获取真实的原生 DOM 对象,可调用所有原生 API(focus、click、style 等)。
在 v-for 循环中使用模板引用时,不能直接使用普通 ref,需要通过函数绑定的方式,将所有 DOM 元素存入数组。
<script setup>
import { ref, onMounted } from 'vue'
// 声明数组存储多个 DOM 引用
const listRefs = ref([])
onMounted(() => {
// 遍历所有 li 元素,设置样式
listRefs.value.forEach(item => {
item.style.color = 'red'
})
})
</script>
<template>
<ul>
<li v-for="item in 3" :key="item" :ref="el => { if (el) listRefs.value.push(el) }">
项目 {{ item }}
</li>
</ul>
</template>:ref="el => {}":动态函数绑定,el 为当前 DOM 元素;
必须做非空判断 if (el),避免渲染时存入无效值;
数组顺序与 v-for 渲染顺序完全一致。
模板引用不仅可以绑定 DOM 元素,还可以绑定子组件实例,用于访问子组件的响应式数据、方法。
<script setup>
import { ref, onMounted } from 'vue'
import Child from './Child.vue'
// 接收子组件实例
const child = ref(null)
onMounted(() => {
// 调用子组件暴露的方法
child.value.sayHello()
})
</script>
<template>
<Child ref="child" />
</template><script setup> 下的组件默认封闭,父组件无法直接访问内部数据,需通过 defineExpose 显式暴露。
<script setup>
// 子组件方法
const sayHello = () => {
console.log('Hello from Child Component')
}
// 暴露属性/方法给父组件
defineExpose({
sayHello
})
</script>在 TS 项目中,为模板引用添加类型标注,提升代码健壮性,避免类型错误。
<script setup lang="ts">
import { ref, onMounted } from 'vue'
// 标注 input 元素类型,初始值 null
const input = ref<HTMLInputElement | null>(null)
onMounted(() => {
// 类型安全访问
input.value?.focus()
})
</script>// 获取子组件实例类型
const child = ref<InstanceType<typeof Child> | null>(null)访问时机 模板引用的 .value 仅在 onMounted 生命周期后才有值,挂载前访问为 null。
空值安全 访问 DOM 时推荐使用可选链操作符 ?.,避免空值报错:input.value?.focus()。
使用原则 Vue 是数据驱动框架,优先使用数据绑定操作视图,仅在必要时使用模板引用操作 DOM。
响应式特性 模板引用是响应式的,但修改引用不会触发视图更新,仅用于存储实例。
模板引用通过 ref 绑定 DOM/ 组件,脚本变量名与模板 ref 必须一致;
仅在 onMounted 后可安全访问,v-for 需用函数绑定引用数组;
子组件需通过 defineExpose 暴露接口,父组件才能调用其方法;
TS 中通过类型标注提升代码安全性,配合可选链避免空值异常。