vue 的 dom 更新是异步的,需结合 nexttick 与生命周期钩子确保 dom 就绪:mounted 中用 nexttick 保证子组件和完整 dom 渲染完成;updated 中再调用 nexttick 避免读取未落地的 dom;created 中必须用 nexttick 才能访问 $refs;组合式 api 推荐 onmounted + nexttick 显式组合。

Vue 的 DOM 更新是异步的,生命周期钩子本身并不保证 DOM 已就绪。想在正确时机操作真实 DOM,必须结合 nextTick 与具体钩子的语义来安排执行时机。
mounted 中用 nextTick 确保子组件和完整 DOM 就绪
mounted 触发时,父组件的模板已挂载,但子组件可能还在初始化、v-if 分支尚未渲染、或 $refs 对应的元素因条件未满足而不存在。直接访问往往取不到目标节点。
- 不安全写法:
this.$refs.input.focus()—— 可能报错或无效 - 安全写法:在
nextTick回调中操作,此时整个组件树完成首次渲染,所有条件判断已生效,真实 DOM 节点确定可用
updated 钩子内再套 nextTick 避免“更新中读取”问题
updated 在响应式数据变化引起视图重绘后触发,但它只表示“更新开始”,不表示“DOM 已落地”。尤其当更新涉及 v-for 重排、第三方库(如 Chart.js)初始化、或依赖 layout 的测量(如 getBoundingClientRect)时,需进一步等待。
- 例如:在 updated 中调用
this.$refs.list.scrollHeight,可能拿到旧高度 - 应改写为:
this.$nextTick(() => { /* 测量或聚焦等操作 */ })
created 中必须用 nextTick 才能访问 $refs
created 阶段 DOM 根本没生成,this.$refs 全为空对象。任何基于 DOM 的逻辑(如预设焦点、计算初始尺寸)都得延迟。
- 常见错误:在 created 里直接
this.$refs.canvas.getContext('2d') - 正确做法:包裹进
this.$nextTick,它会在首次挂载完成、DOM 插入文档后执行
组合式 API 中 onMounted + nextTick 更清晰
Vue 3 推荐写法是将生命周期与 nextTick 显式组合,语义更明确:
onMounted(() => { nextTick(() => { /* DOM 真正可用 */ }) })- 比单独写
onMounted更稳妥,尤其在使用teleport、动态组件或服务端渲染(SSR)降级场景下










