vue3.x教程-nextTick() 延缓执行 作者:马育民 • 2026-07-26 20:21 • 阅读:10001 # 提出问题 下面的代码,为什么执行 `name.value = '李雷'` 后,获取 `id="name"` 的控件的值,还是空值? ``` 修改 ``` ### 分析 改数据后 → DOM 不会马上更新 ### 解决 使用 `nextTick()` 延缓执行 # 介绍 Vue 在**更新 DOM 时是异步执行**的: 当响应式数据发生变更,Vue 不会立刻去更新 DOM,而是把这些 DOM 更新缓存到一个队列;等**当前同步代码全部执行完毕**之后,再统一处理队列、更新 DOM。 所以:**修改数据后,立刻去获取 DOM,拿到的还是更新前的旧 DOM**。 `nextTick()` 的作用:**等待下一次 DOM 更新完成后执行回调代码**。 ### 一句话解释 改数据后 → DOM 不会马上更新,`nextTick ()` **让后面的代码延后执行**,等 DOM 真正刷新完毕后,再执行。 # 使用 组合式 API ### await、async 修改上面的 `handle()` 函数,如下: ``` async function handle() { name.value = '李雷' // 延缓后面的代码执行,等 DOM 真正刷新完毕后,再执行 await nextTick() console.log(document.querySelector('#name').value) // 新值 } ``` ### 回调方式 修改上面的 `handle()` 函数,如下: ``` function handle() { name.value = '李雷' // 等 DOM 真正刷新完毕后,再执行 nextTick(() => { console.log(document.querySelector('#name').value) // 新值 }) } ``` ### 原理 执行流程: 1. 修改响应式变量 `name.value` 2. Vue 将 DOM 更新任务推入**微任务队列**(不立即执行) 3. 继续执行当前同步代码(此时 DOM 未变化) 4. 同步代码执行结束 5. 执行微任务:批量更新真实 DOM 6. DOM 更新完成后,执行 `nextTick()` 的回调(如果有多个`nextTick()`,都会执行) ### 队列机制特点 1. **多次修改数据只会触发一次 DOM 更新** ``` state.a = 1 state.a = 2 state.a = 3 // Vue只会执行1次DOM渲染,优化性能 ``` 2. nextTick 的回调会挂载在**DOM 更新之后**的微任务中 ### Vue3 nextTick 内部异步策略(优先级) Vue3 内部自动降级选择异步方案: 1. 优先使用 `Promise.then`(微任务) 2. 不支持 Promise 环境 → `MutationObserver` 3. 再降级 → `setTimeout`(宏任务) > > 绝大多数现代浏览器都是 **Promise 微任务** # 典型使用场景 ### 什么时候需要 nextTick? **修改响应式数据 → 紧接着要操作 DOM(获取元素、聚焦、滚动、读取元素大小)** 满足这个流程,就要加 nextTick ### 场景 1:修改数据后,立刻获取 / 操作最新 DOM 元素 - 获取输入框 `offsetHeight`、元素尺寸 - 获取 `ref` 绑定 DOM 节点 ``` 内容 ``` ### 场景 2:动态创建 DOM 后,操作第三方 DOM 库 如 echarts、富文本编辑器、拖拽库,需要 DOM 存在才能初始化 ``` tableVisible.value = true await nextTick() echarts.init(dom) // 此时dom已经渲染完成 ``` ### 场景 3:v-if /v-show 切换后操作元素 `v-if` 会销毁重建 DOM,切换后必须 nextTick 等待节点挂载。 ### 场景 4:滚动到新增列表项 请求追加列表数据,想自动滚动到最后一条 ``` list.value.push(...newData) await nextTick() scrollToBottom() ``` # 易错点 ### ❌ 错误:连续多个 nextTick 不要误以为顺序串行 nextTick 全部加入同一轮更新之后执行: ``` state.x = 1 nextTick(()=>console.log(1)) nextTick(()=>console.log(2)) // DOM只更新一次,两个回调连续执行 ``` ### ❌ 误区:nextTick 不能等待接口请求 nextTick **只管 DOM 渲染,不等待异步网络请求** ``` async function demo(){ // 网络请求是独立异步,nextTick等不到接口返回 fetchData().then(res=> list.value = res) await nextTick() // 此时接口还没返回,list还没赋值! } ``` ### ❌ 不要滥用 nextTick 很多场景可以通过**数据驱动**解决,尽量避免直接操作 DOM,只有必须获取原生 DOM 时才使用。 # 总结 1. Vue 数据更新 → DOM 异步延迟刷新; 2. nextTick:注册回调,**等待本轮 DOM 更新完成后运行**; 3. 适用:改数据后立刻读取 / 操作最新 DOM; 4. Vue3 优先使用 `await nextTick()`; 5. 本质利用浏览器微任务实现,批量渲染优化性能。 原文出处:http://www.malaoshi.top/show_1GW3kSSBcD9l.html