当前位置: 首页 > news >正文

Vue: 模板引用 (Template Refs)

概述

        Vue 的声明式渲染模型抽象了大部分 DOM 操作,但在某些情况下仍需直接访问 DOM 元素或组件实例。模板引用 (ref) 提供了这种能力,允许我们在组件挂载后获得对特定 DOM 元素或子组件实例的直接引用。

基础用法

在模板中声明引用

<template><input ref="myInput">
</template>

在组合式 API 中访问引用

<script setup>
import { useTemplateRef, onMounted } from 'vue'// 声明引用,参数必须与模板中的 ref 值匹配
const myInput = useTemplateRef('myInput')onMounted(() => {// 在挂载后访问引用myInput.value.focus()
})
</script>

模板引用生命周期流程图

组件上的引用

引用子组件实例

<script setup>
import { useTemplateRef, onMounted } from 'vue'
import Child from './Child.vue'const childRef = useTemplateRef('child')onMounted(() => {// childRef.value 持有 <Child /> 的实例console.log(childRef.value) // 子组件实例
})
</script><template><Child ref="child" />
</template>

子组件暴露接口

<!-- Child.vue -->
<script setup>
import { ref } from 'vue'const a = 1
const b = ref(2)// 显式暴露属性和方法
defineExpose({a,b,someMethod() {// 方法实现}
})
</script>

v-for 中的模板引用

基本用法

<script setup>
import { ref, useTemplateRef, onMounted } from 'vue'const list = ref([1, 2, 3])
const itemRefs = useTemplateRef('items')onMounted(() => {// itemRefs.value 是一个数组,包含所有列表项元素console.log(itemRefs.value) // [li, li, li]
})
</script><template><ul><li v-for="item in list" ref="items">{{ item }}</li></ul>
</template>

函数模板引用

使用函数处理引用

<script setup>
import { ref } from 'vue'const inputRef = ref(null)// 引用处理函数
const setInputRef = (el) => {inputRef.value = elif (el) {console.log('元素已挂载:', el)} else {console.log('元素已卸载')}
}
</script><template><input :ref="setInputRef"><!-- 或者使用内联函数 --><input :ref="(el) => { inputRef.value = el }">
</template>

类型定义 (TypeScript)

为模板引用标注类型

<script setup lang="ts">
import { useTemplateRef, onMounted } from 'vue'// Vue 会自动推断类型,但也可以显式标注
const input = useTemplateRef<HTMLInputElement>('my-input')onMounted(() => {if (input.value) {input.value.focus() // TypeScript 知道这是一个 HTMLInputElement}
})
</script><template><input ref="my-input" />
</template>

为组件引用标注类型

<script setup lang="ts">
import { useTemplateRef, onMounted } from 'vue'
import Child from './Child.vue'// 定义子组件实例类型
type ChildInstance = InstanceType<typeof Child>const childRef = useTemplateRef<ChildInstance>('child')onMounted(() => {if (childRef.value) {// 可以访问子组件暴露的属性和方法console.log(childRef.value.a)}
})
</script>

最佳实践与注意事项

1. 引用访问时机

<script setup>
import { useTemplateRef, onMounted, watchEffect } from 'vue'const input = useTemplateRef('my-input')// 正确:在挂载后访问
onMounted(() => {if (input.value) {input.value.focus()}
})// 使用 watchEffect 处理引用变化
watchEffect(() => {if (input.value) {// 元素已挂载console.log('元素可用:', input.value)} else {// 元素未挂载或已卸载console.log('元素不可用')}
})
</script>

2. 条件渲染中的引用

<template><div><button @click="showInput = !showInput">切换显示</button><input v-if="showInput" ref="myInput"></div>
</template><script setup>
import { useTemplateRef, watch } from 'vue'const showInput = ref(false)
const myInput = useTemplateRef('my-input')// 监听条件变化
watch(showInput, (newVal) => {if (newVal) {// 需要等待下一次 DOM 更新nextTick(() => {if (myInput.value) {myInput.value.focus()}})}
})
</script>

3. 引用管理策略

场景推荐方法注意事项
单个元素引用useTemplateRef确保名称匹配
动态元素引用函数引用处理卸载情况
列表引用v-for + ref引用值为数组
组件引用组件ref + defineExpose避免过度暴露

总结

核心概念

  1. 模板引用提供直接访问 DOM 元素和组件实例的能力

  2. 使用 useTemplateRef() 在组合式 API 中获取引用

  3. 引用值在组件挂载前为 null,挂载后指向实际元素/实例

  4. 组件引用需要通过 defineExpose 显式暴露接口

适用场景

  • 焦点管理

  • 动画触发

  • 第三方库集成

  • 测量元素尺寸/位置

  • 需要直接 DOM 操作的特定情况

注意事项

  1. 避免过度使用引用,优先使用声明式方法

  2. 注意引用访问时机,确保元素已挂载

  3. 处理条件渲染中的引用变化

  4. 组件引用应通过 props/emit 优先,引用作为最后手段

        通过合理使用模板引用,可以在保持 Vue 声明式优势的同时,处理需要直接 DOM 操作的边缘情况。


文章转载自:

http://5eVo16TR.qqkLk.cn
http://2aKMALjb.qqkLk.cn
http://8QYzg8eZ.qqkLk.cn
http://YIRmEuQt.qqkLk.cn
http://Nj3PVcq4.qqkLk.cn
http://Gr6DNHaN.qqkLk.cn
http://tnkmIrK5.qqkLk.cn
http://oEtCDBpF.qqkLk.cn
http://FMcCLmHY.qqkLk.cn
http://lu8i5obr.qqkLk.cn
http://FZN0mB7C.qqkLk.cn
http://fSExFsVb.qqkLk.cn
http://mNuB2TTj.qqkLk.cn
http://0a7JakTX.qqkLk.cn
http://YeaMEmJL.qqkLk.cn
http://c51rrwkC.qqkLk.cn
http://BUNo8FEN.qqkLk.cn
http://etZCZMjm.qqkLk.cn
http://2eIwgoXX.qqkLk.cn
http://HnleBkHz.qqkLk.cn
http://ymCFAdx0.qqkLk.cn
http://5hkBbdgS.qqkLk.cn
http://EMH9nWun.qqkLk.cn
http://lhoOwhwV.qqkLk.cn
http://bqqjfBki.qqkLk.cn
http://P5TVIVsh.qqkLk.cn
http://yjhsoelj.qqkLk.cn
http://0rbfjlaG.qqkLk.cn
http://tP0v8KWv.qqkLk.cn
http://wSC6lrXN.qqkLk.cn
http://www.dtcms.com/a/384276.html

相关文章:

  • Web2 vs Web3
  • 上海交大3D体素赋能具身导航!BeliefMapNav:基于3D体素信念图的零样本目标导航
  • SAP-ABAP:SAP ABAP中的JSON序列化利器:/UI2/CL_JSON=>SERIALIZE完全指南实例详解
  • stm32 can错误处理问题
  • python 自动化从入门到实战-开发一个随机点名系统(6)
  • 如何用 GitHub Actions 为 FastAPI 项目打造自动化测试流水线?
  • godot+visual studio配置c#环境
  • 文件查找失败:‘module‘ at node_modules\sass\sass.node.js:7
  • (一)Vue.js 框架简介
  • Vue 中在 Vue 项目中引入 Cesium 并加载本地离线地图
  • Node.js ≥ 18 安装教程
  • 第四阶段C#通讯开发-4:网络通讯_网络协议
  • 如何实现测试环境隔离临时数据库(pytest+SQLite)
  • 像连接mysql一样连接mongodb
  • 从零开始搞定C++类和对象(下)
  • 企业级实战:构建基于Qt、C++与YOLOv8的模块化工业视觉检测系统
  • TexturePacker 打包 TextAtlas:按顺序排列
  • MyBatis 核心概念与实践指南:从代理模式到性能优化
  • 全链路性能优化实战:从Jmeter压测到系统调优
  • 《华为变革法:打造可持续进步的组织》读书笔记
  • VS Code 通用配置分享(Cursor / QCode / Trae 通用)
  • python 自动化从入门到实战-word转为 PDF 文件(4)
  • Python爬虫实战:研究Pandas,构建地理信息数据采集和分析系统
  • 【Linux】进程概念(二):进程查看与 fork 初探
  • Python 自动化从入门到实战-一键将 Excel 表格转为 PDF 文件(3)
  • FFMPEG FLV
  • Spring Cloud Alibaba 与 Spring Boot、Spring Cloud 的版本兼容性对照
  • 猫头虎AI分享Excel MCP技术解析让AI智能操作Excel表格的完整指南
  • Keka 解压/压缩工具(Mac电脑)
  • 【Linux网络】网络基础概念——带你打开网络的大门