源本科技 | 码上会

Vue3 模板引用

2026/04/22
33
0

引言

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 元素赋值给同名的响应式变量。

  • 脚本部分

    1. 导入 ref 创建响应式引用,onMounted 保证 DOM 渲染完成;

    2. 初始值 null:挂载前模板引用默认指向 null不可提前访问

    3. input.value:获取真实的原生 DOM 对象,可调用所有原生 API(focus、click、style 等)。

v-for 中的模板引用

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>

子组件 Child.vue

<script setup> 下的组件默认封闭,父组件无法直接访问内部数据,需通过 defineExpose 显式暴露。

<script setup>
// 子组件方法
const sayHello = () => {
  console.log('Hello from Child Component')
}

// 暴露属性/方法给父组件
defineExpose({
  sayHello
})
</script>

TypeScript 类型标注

在 TS 项目中,为模板引用添加类型标注,提升代码健壮性,避免类型错误。

原生 DOM 元素

<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)

注意事项

  1. 访问时机 模板引用的 .value 仅在 onMounted 生命周期后才有值,挂载前访问为 null

  2. 空值安全 访问 DOM 时推荐使用可选链操作符 ?.,避免空值报错:input.value?.focus()

  3. 使用原则 Vue 是数据驱动框架,优先使用数据绑定操作视图,仅在必要时使用模板引用操作 DOM。

  4. 响应式特性 模板引用是响应式的,但修改引用不会触发视图更新,仅用于存储实例。


总结

  1. 模板引用通过 ref 绑定 DOM/ 组件,脚本变量名与模板 ref 必须一致;

  2. 仅在 onMounted 后可安全访问,v-for 需用函数绑定引用数组;

  3. 子组件需通过 defineExpose 暴露接口,父组件才能调用其方法;

  4. TS 中通过类型标注提升代码安全性,配合可选链避免空值异常。