R后悔药 Rue.js
  • 首页
    • 深度指南
    • 实战例子
    • 快速上手
    • 路由指南
    • 术语表
    • 错误代码参考
  • API
    • 合作伙伴
    • 插件
    • 组件库
    • 工具链
    • Text.js
    • 新闻简报
    • 常见问题
    • 团队
    • 版本发布
    • 社区指南
    • 行为规范
    • 隐私政策
  • 赞助
  • 合作伙伴
设置
目录统计
总条目
  • 你好,世界
  • 处理输入
  • Attribute 绑定
  • 条件与循环
  • 表单绑定
  • 简单组件
  • useApp().component 注册
  • Reactive Props Destructure
  • Props 与 useSetup
  • Slots 插槽
  • 原生 Web Components
  • Web Components 分项测试
  • 基础元素与自闭合标签
  • 表达式与插值
  • 属性、className、style 与 Props
  • 对象展开属性(spread props)
  • 条件渲染(?:、&&、null)
  • v-if / r-if 指令
  • v-show / r-show 指令
  • v-pre / r-pre 指令
  • v-once / r-once 指令
  • v-memo / r-memo 指令
  • v-text / r-text 指令
  • v-html / r-html 指令
  • v-on / r-on 指令
  • v-model / r-model 指令
  • 列表渲染与 key
  • v-for / r-for 指令
  • Template 无包装容器
  • Scoped Style 组件作用域样式
  • Fragments(<> … </>)
  • children 插槽与嵌套
  • 组件与 Props 传递
  • 动态组件(Component)
  • Suspense 异步边界
  • 异步组件懒水合
  • 事件处理
  • 受控输入
  • Refs 基础
  • Markdown 编辑器
  • 获取数据
  • 服务端预取
  • 资源
  • 资源(纯 JSX)
  • Rue Islands 总览
  • Island:client:load
  • Island:client:idle
  • Island:client:visible
  • Island:client:media
  • Island:client:interaction
  • Island:client:none
  • Island:client:only
  • Island:安全 Props
  • Island:Manifest Props
  • Island:client:* 编译
  • Context
  • 语言切换(_ 模型)
  • 路由 Demo:总览(嵌套路由)
  • 路由 Demo:守卫(beforeEnter)
  • 路由 Demo:实验页(受守卫保护)
  • 基础计数器
  • shallowRef 浅层 ref
  • triggerRef 手动触发
  • customRef 自定义 ref
  • onActivated 缓存生命周期
  • toRef 响应式句柄
  • toRefs 响应式解构
  • isRef 判定示例
  • isProxy 代理判断
  • isReadonly 判断
  • nextTick 真实业务场景
  • watchPostEffect DOM 读取
  • watchSyncEffect 同步防线
  • onWatcherCleanup 请求清理
  • effectScope 批量停止
  • onScopeDispose 作用域清理
  • getCurrentScope 作用域探针
  • 渲染函数计数器
  • onRenderTracked 调试
  • onRenderTriggered 调试
  • onDeactivated
  • onErrorCaptured 错误捕获
  • useState 计数器
  • 条件渲染
  • map 列表渲染
  • Todo 应用
  • 基础待办事项
  • 本地待办事项
  • 用户资料编辑
  • useState 数组
  • useState 对象
  • 本地 ref 计数器
  • 排序、筛选与网格
  • Store Query Sync 与 URL 状态
  • 树状视图
  • SVG 图表
  • SVG 共享标签命名空间
  • 带过渡动效的模态框
  • Transition mode
  • 子调父方法
  • 父控子计数
  • 组件级 v-model
  • 命名 v-model
  • 组件 emit
  • Hello children
  • 基础 children Box
  • 嵌套 children Box
  • Layout children
  • 过渡动效

nextTick 真实业务场景

现在这个页面只负责组织展示:原来的基础 demo 还在,同时把业务 demo 全拆成了独立组件,并补了表格筛选、提交校验、弹窗测量这类更偏数据流的 nextTick 场景。

保留原始 demo
读取最新 DOM 文本

基础场景:状态更新后同步读 DOM 会拿到旧值,await nextTick() 后才是最新文本。

基础认知调试刷新顺序DOM 同步读取

这是最基础的版本:先改响应式状态,再分别在同步阶段和 nextTick() 之后读取 DOM 文本,能直接看到同一轮刷新前后的差异。

当前 DOM 文本
0
同步读取到的 DOM 文本
尚未读取
await nextTick() 后读取
尚未读取
本轮步骤
  • 1. 点击按钮后先执行 count.value += 1
  • 2. 紧接着读取当前 span.textContent
  • 3. await nextTick() 后再读取一次 DOM
新增业务 demo
真实业务里 nextTick 怎么用

这里除了原来的 3 个业务场景,还新增了“表格筛选后滚到首条结果”“提交后聚焦错误字段”“弹窗打开后测量列表高度”3 个更偏数据流和表单流的真实例子。

业务场景 1
消息流自动滚动

新增聊天、订单轨迹或系统通知后,等待列表完成渲染,再滚动到最底部。

客服聊天订单时间线系统日志

聊天窗口、订单轨迹、告警流常见的需求是“新增一条后自动滚到底部”。如果同步读取 scrollHeight,拿到的还是旧值,因此要等 nextTick() 之后再滚动。

订单通知流
4 条消息
09:20 新订单 #A1024 已创建
09:21 支付回调已确认
09:22 仓库开始拣货
09:23 配送单已推送
同步读取到的 scrollHeight
尚未追加
await nextTick() 后的高度
尚未追加
本轮步骤
  • 1. 追加一条新的订单通知
  • 2. 同步读取列表 scrollHeight 并尝试滚动
  • 3. await nextTick() 后再读取高度并滚到底部
业务场景 2
打开面板后自动聚焦

搜索弹层、筛选抽屉、编辑表单打开后,要在 DOM 挂载完成后再 focus 输入框。

高级筛选搜索抽屉新增表单

搜索弹层、抽屉、筛选面板在打开后往往需要马上聚焦第一个输入框。问题在于输入框是在本轮更新里新挂载的,所以必须等 nextTick() 之后再调用 focus()。

同步阶段状态
尚未打开
await nextTick() 后状态
尚未聚焦
本轮步骤
  • 1. 打开高级筛选面板
  • 2. 同步阶段输入框还没有挂载完成
  • 3. await nextTick() 后聚焦关键字输入框
业务场景 3
展开后测量高度

手风琴、详情抽屉展开后,需要在布局刷新完成后测量高度以驱动滚动和动画。

订单详情商品详情折叠面板

手风琴、订单详情抽屉、商品详情区经常要在展开后测量高度,去驱动滚动、动画或埋点。同步测量拿到的还是旧高度,要等 nextTick() 后再测一次。

订单详情卡片
订单 #A1024
已收起
支付状态:已支付
配送方式:同城急送
仓库:上海 3 号仓
下单时间:09:20
同步读取到的高度
尚未测量
await nextTick() 后高度
尚未测量
本轮步骤
  • 1. 切换订单详情区的展开状态
  • 2. 同步阶段读取到的还是旧高度
  • 3. await nextTick() 后再拿到新高度
业务场景 4
表格筛选后滚到首条结果

切换订单筛选条件后,等待表格结果刷新,再自动滚到新的首条命中记录。

风控台账售后列表工单筛选

客服工单、风控台账、售后列表经常会在筛选后自动滚到首条命中结果。问题在于筛选结果也是本轮更新的一部分,必须等 nextTick() 后再定位首条新结果。

订单号客户状态金额备注
A-1024上海徐汇门店待发货¥1,280等待波次出库
A-1025苏州工业园已完成¥980已签收
A-1026深圳南山客户待风控¥2,430等待人工复核
A-1027北京朝阳客户退款中¥560退款审核中
A-1028杭州西湖门店待发货¥1,120拣货完成
A-1029武汉光谷仓待风控¥3,100需补充发票信息
A-1030成都高新区客户退款中¥760等待退款到账
A-1031广州天河客户已完成¥640回访完成
A-1032天津滨海门店待发货¥1,860待分配骑手
A-1033厦门湖里客户待风控¥1,420身份核验异常
同步读取到的首条结果
尚未筛选
await nextTick() 后定位到
尚未定位
本轮步骤
  • 1. 切换筛选条件,表格准备重新渲染
  • 2. 同步阶段读取到的还是旧首条结果
  • 3. await nextTick() 后滚到新的首条命中记录
业务场景 5
提交后聚焦错误字段

表单提交后,等错误样式和提示渲染完成,再自动 focus 第一个错误输入框。

开户表单地址编辑审批提单

表单提交通常要在渲染出错误提示后,把焦点移动到第一个错误字段,方便用户立刻修正。错误样式和提示文案同样属于本轮更新,所以要等 nextTick() 之后再 focus。

同步阶段识别到的字段
尚未提交
await nextTick() 后结果
尚未聚焦
本轮步骤
  • 1. 点击提交后先更新错误状态
  • 2. 同步阶段还拿不到新的首个错误字段
  • 3. await nextTick() 后再 focus 首个错误输入框
业务场景 6
弹窗打开后测量列表高度

批量发送或通知弹窗打开后,等列表挂载完成,再测量高度决定布局策略。

消息中心批量通知营销弹窗

营销、消息中心、批量通知类弹窗经常要在打开后测量接收人列表的高度,决定是直接展开还是切换成固定高度滚动容器。弹窗内容本身是新挂载的,必须等 nextTick() 后再测量。

同步读取到的高度
尚未打开
await nextTick() 后高度
尚未测量
布局决策
等待测量
本轮步骤
  • 1. 打开批量发送弹窗
  • 2. 同步阶段列表容器还没真正挂载完成
  • 3. await nextTick() 后再测量列表高度决定布局策略
页内导航
文档
  • 深度指南
  • 实战例子
  • 快速上手
  • 术语表
  • 错误码参照表
关于
  • 常见问题
  • 团队
  • 版本发布
  • 社区指南
生态
  • 插件
  • 组件库
  • 路由指南
  • Text.js
© 2024-2026 Xiangmin Liu
Rue.JS