vue 的 ref 是静态引用而非响应式代理,仅在挂载后指向真实 dom 或组件实例,不参与虚拟 dom diff、不被依赖追踪,修改 ref 本身不会触发视图更新,必须配合生命周期(如 mounted)和 $nexttick 确保操作时机。

Vue 的 ref 引用本身不参与虚拟 DOM 的 diff 和更新流程,它只是 Vue 实例上一个指向真实 DOM 元素或组件实例的“快捷入口”。ref 不是响应式数据,也不被 Vue 的依赖追踪系统监听,它的更新机制与虚拟 DOM 的渲染周期是解耦的。
ref 是静态引用,不是响应式代理
当你在模板中写 ref="inputEl",Vue 在挂载(mounted)阶段把对应的真实 DOM 节点赋值给 this.$refs.inputEl。这个赋值只发生一次(或在 v-if 切换、v-for 重渲染时重新赋值),之后 this.$refs.inputEl 就是一个普通 DOM 对象引用,不会随数据变化自动刷新。
- 它不经过响应式系统,修改
this.$refs.xxx本身不会触发视图更新 - 它不参与虚拟 DOM 的 patch 过程——Vue 不会为 ref 做 diff,也不会基于 ref 决定是否重绘
- 即使你手动改了
this.$refs.inputEl.value,Vue 也不知道,除非你同步更新对应的数据源(如 v-model 绑定的 ref 或 reactive 字段)
ref 获取时机依赖渲染生命周期
ref 只有在元素真实挂载到 DOM 后才可访问。常见误区是:在 created 钩子中尝试读取 this.$refs.xxx,此时返回 undefined。
- 必须等到
mounted钩子执行完毕,DOM 已插入文档流,ref 才就位 - 若元素被
v-if控制显示/隐藏,ref 会在条件为 true 时创建,为 false 时设为undefined - 使用
v-for渲染多个同名 ref 时,this.$refs.xxx返回数组(而非单个元素),需注意索引和顺序
配合 $nextTick 确保 DOM 更新后操作
当数据变更触发重新渲染后,虚拟 DOM 已计算完毕,但真实 DOM 尚未完成替换。此时直接读取 ref 可能拿到旧节点或未更新的值。
- 例如:修改一个响应式变量 → 触发模板重渲染 → 想立刻 focus 新生成的 input → 必须用
this.$nextTick(() => this.$refs.input.focus()) -
$nextTick本质是等待 Vue 完成 DOM patch 后的微任务队列,确保 ref 指向的是最新渲染出的节点 - 不加 $nextTick 的常见问题:focus 失败、offsetHeight 为 0、getBoundingClientRect 返回旧尺寸
ref 与组件通信的边界清晰
ref 用于父组件获取子组件实例(如调用子组件方法),但该引用仅在父组件内有效,且子组件无法反向访问父组件的 ref —— 这是 Vue 明确的设计约束。
- 子组件通过
defineExpose(Vue 3)或expose选项显式暴露方法,父组件才能通过 ref 调用 - ref 拿到的是组件实例(proxy 对象),不是其内部的 $el;若需操作子组件根 DOM,应由子组件提供方法封装,而非父组件越权操作
- 避免滥用 ref 替代 props / emit:ref 应用于“命令式控制”(如播放视频、滚动定位),而非状态传递
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











