watcher 怎么清理,flush 配置有什么用?
先理解原理和示例,再练习完整口述与追问。
回答要点
副作用失效时取消旧请求或忽略旧结果。默认 watcher 回调与组件 DOM 更新有调度先后,访问自身更新后 DOM 可按需用 flush: 'post'。同步 flush 不做常规批量处理,要谨慎。
Vue3.5+ 的 onWatcherCleanup 要在同步执行阶段注册;回调提供的 onCleanup 机制约束不同,也应尽早注册清理。
原理拆解
副作用重新运行或作用域结束时,应清理上一轮建立的外部资源。watch 回调可接收 onCleanup 登记清理;Vue3.5 的 onWatcherCleanup 有同步调用时机要求,不能在 await 后随意登记。默认 watcher 通常在父更新后、自身 DOM 更新前执行;flush:post 适合读取更新后 DOM,flush:sync 则立即执行且失去常见批处理收益。
示例与推演
对关键词搜索,先创建 AbortController 并同步登记清理,再发请求;下一次关键词变化时清理旧控制器。若底层 API 不支持取消,再加请求序号忽略过期响应。为测量条件渲染后的元素高度,可选择 post 或等待 nextTick;不要把所有 watcher 改 sync 来掩盖时序理解问题。
易错点
异步创建、脱离组件作用域的 watcher 可能需要手动 stop。清理取消只影响客户端工作,不能保证后端撤销写操作;旧 finally 同样要保护当前 loading。
参考回答可直接练习口述
watcher 发异步请求时,我会在失效时取消旧请求或让旧结果失效,防止过期响应覆盖新状态。默认回调在所属组件 DOM 更新前运行,需要读更新后 DOM 可以用 flush: post;sync 模式立即触发,频繁修改时会失去批量优势。Vue3.5+ 的 onWatcherCleanup 必须在同步回调阶段注册,不能等 await 后再调用。
面试官可能继续问追问与完整解答展开收起
追问
组件卸载会自动停止哪些 watcher?异步回调里创建的 watcher 为什么需要额外管理?Vue3 官方 watcher 文档
追问回答
在 setup 等归属组件的同步上下文创建的 watcher 通常会在卸载时自动停止。setTimeout 等异步回调中另建 watcher 不一定归属原组件,需要保存 stop 并手动清理。回调参数 onCleanup 绑定 watcher,不受 onWatcherCleanup 同样的同步注册限制,但尽早注册可避免清理时机竞争。