Template Refs 模板引用

发布时间:2026/6/27 1:11:09

Template Refs 模板引用 文章目录前言一、获取 DOM 元素1.1 基本用法1.2 挂载前 ref 为 null1.3 常见 DOM 操作二、获取子组件实例2.1 调用子组件方法2.2 defineExpose 的作用三、v-for 中的 ref3.1 函数形式收集3.2 数组形式Vue 3.5四、第三方库初始化4.1 ECharts 示例4.2 注意生命周期五、TypeScript 类型5.1 DOM 元素类型5.2 组件实例类型六、函数 ref6.1 动态绑定6.2 与字符串 ref 对比七、面试聚焦7.1 挂载前 ref 为 null7.2 script setup 子组件默认暴露什么7.3 为什么需要 defineExpose八、易混淆点九、思考与练习总结前言Template Refs模板引用让你在 Composition API 中获取模板里的 DOM 元素或子组件实例便于调用原生方法、第三方库初始化或父调子方法。本篇会讲清楚ref 获取 DOM 与组件实例defineExpose暴露子组件 APIv-for中的 ref 收集TypeScript 类型与常见陷阱一、获取 DOM 元素1.1 基本用法template input refinputRef placeholder自动聚焦 / button clickfocusInput聚焦/button /template script setup import { ref, onMounted } from vue const inputRef ref(null) onMounted(() { inputRef.value?.focus() }) const focusInput () { inputRef.value?.focus() } /script规则模板中refinputRef与 script 中同名ref(null)自动绑定。1.2 挂载前 ref 为 nullconstinputRefref(null)console.log(inputRef.value)// nullsetup 同步阶段onMounted((){console.log(inputRef.value)// input DOM 元素})ref 在组件挂载完成后才有值。setup 同步执行期间、onMounted 之前访问都是null需用可选链?.或放在 onMounted / nextTick 中。1.3 常见 DOM 操作script setup import { ref, onMounted } from vue const inputRef ref(null) const containerRef ref(null) onMounted(() { // 输入框 inputRef.value?.focus() inputRef.value?.select() // 滚动 containerRef.value?.scrollIntoView({ behavior: smooth }) // 尺寸 const { width, height } containerRef.value.getBoundingClientRect() }) /script template input refinputRef / div refcontainerRef内容区域/div /template二、获取子组件实例2.1 调用子组件方法!-- ChildForm.vue -- script setup import { ref } from vue const formData ref({ name: }) const validate () { if (!formData.value.name) return false return true } const reset () { formData.value { name: } } // script setup 默认不暴露必须 defineExpose defineExpose({ validate, reset }) /script template input v-modelformData.name / /template!-- Parent.vue -- template ChildForm refformRef / button clicksubmit提交/button /template script setup import { ref } from vue import ChildForm from ./ChildForm.vue const formRef ref(null) const submit () { if (formRef.value?.validate()) { // 提交逻辑 } } /script2.2 defineExpose 的作用场景行为Options API子组件 methods 默认可被父组件 ref 访问script setup默认什么都不暴露父组件 ref 拿不到内部defineExpose显式指定父组件可访问的属性/方法// 暴露部分defineExpose({validate,reset})// 暴露全部不推荐defineExpose({...instance})三、v-for 中的 ref3.1 函数形式收集template div v-foritem in list :keyitem.id :ref(el) setItemRef(el, item.id) {{ item.name }} /div /template script setup import { ref, onMounted } from vue const list ref([ { id: 1, name: A }, { id: 2, name: B } ]) const itemRefs ref(new Map()) const setItemRef (el, id) { if (el) { itemRefs.value.set(id, el) } else { itemRefs.value.delete(id) // 卸载时 el 为 null } } onMounted(() { console.log(itemRefs.value.get(1)) // 第一个 div }) /script3.2 数组形式Vue 3.5template div v-foritem in list :keyitem.id refitemRefs {{ item.name }} /div /template script setup import { ref, onMounted } from vue const itemRefs ref([]) onMounted(() { console.log(itemRefs.value) // [div, div, ...] }) /script列表更新时 ref 数组会同步更新。函数形式更灵活适合按 id 索引。四、第三方库初始化4.1 ECharts 示例template div refchartRef stylewidth: 600px; height: 400px;/div /template script setup import { ref, onMounted, onUnmounted } from vue import * as echarts from echarts const chartRef ref(null) let chartInstance null onMounted(() { chartInstance echarts.init(chartRef.value) chartInstance.setOption({ /* ... */ }) }) onUnmounted(() { chartInstance?.dispose() }) /script4.2 注意生命周期第三方库通常需要onMounted中初始化ref 已有 DOMonUnmounted中销毁避免内存泄漏数据变化时在 watch 中update而非重复 init五、TypeScript 类型5.1 DOM 元素类型import{ref,onMounted}fromvueconstinputRefrefHTMLInputElement|null(null)constdivRefrefHTMLDivElement|null(null)onMounted((){inputRef.value?.focus()// 有类型提示})5.2 组件实例类型importtype{ComponentPublicInstance}fromvueimportChildFormfrom./ChildForm.vue// 方式一InstanceTypeconstformRefrefInstanceTypetypeofChildForm|null(null)// 方式二自定义暴露的类型interfaceChildFormExpose{validate:()booleanreset:()void}constformRefrefChildFormExpose|null(null)配合defineExpose时可单独定义 Expose 接口供父组件使用。六、函数 ref6.1 动态绑定template input :ref(el) { inputRef el } / /template script setup let inputRef null // 也可配合 ref() /script函数 ref 在元素挂载时传入 el卸载时传入null适合条件渲染或 v-for。6.2 与字符串 ref 对比方式写法适用同名 ref 变量refinputRefconst inputRef ref(null)单个元素最常用函数 ref:reffnv-for、动态、条件渲染七、面试聚焦7.1 挂载前 ref 为 nullsetup 同步阶段和 onMounted 之前ref.value 为null。访问 DOM 或调用子组件方法必须在 onMounted、nextTick 或事件回调中。7.2 script setup 子组件默认暴露什么什么都不暴露。父组件通过 ref 无法访问子组件内部必须用defineExpose显式暴露需要的方法或数据。7.3 为什么需要 defineExposescript setup 将组件内部封闭避免父组件随意访问实现细节符合封装原则。只暴露必要的 API如 validate、focus。八、易混淆点ref 名称必须匹配模板refxxx与 scriptconst xxx ref(null)同名。挂载前为 null不要用 onBeforeMount 里操作 DOM ref。script setup 子组件需 defineExpose否则 formRef.value.validate 为 undefined。v-for 的 ref 用函数或数组单个 ref 变量只会指向最后一个元素。组件 ref vs DOM ref组件实例调用方法DOM ref 操作 .focus、.scrollIntoView 等。九、思考与练习1.Template Ref 的作用是什么解析获取模板中 DOM 元素或子组件实例的直接引用用于原生 DOM 操作、调用子组件方法、第三方库初始化。2.为什么 onMounted 之前 ref 是 null解析DOM 尚未渲染完成ref 绑定发生在挂载过程中挂载完成后才有值。3.script setup 子组件如何让父组件调用 validate解析子组件defineExpose({ validate })父组件formRef.value?.validate()。4.v-for 中如何收集多个元素 ref解析用函数 ref:ref(el) setRef(el, id)存 Map或 Vue 3.5 用 ref 数组。5.何时用 ref 操作 DOM何时用声明式解析focus、scroll、第三方库 init 等命令式操作用 ref展示、样式、数据绑定优先声明式模板。总结Template Refrefname 同名ref(null)获取 DOM 或组件实例挂载前 nullonMounted / nextTick 后再访问defineExposescript setup 子组件显式暴露给父组件 ref 调用v-for函数 ref 或 ref 数组收集多个元素TSHTMLInputElement、InstanceTypetypeof Comp标注类型

相关新闻