为何Vue中ref初始返回undefined,回调中可获取对应元素?
问题原因解析:修改响应式数据后立即访问$refs返回undefined的原因
核心原因:Vue的异步更新机制
当你修改showBlock这类响应式数据时,Vue不会立刻更新DOM,而是把DOM更新操作加入异步更新队列。只有当前所有同步代码执行完毕后,Vue才会批量处理队列里的更新请求,完成DOM的渲染或修改。
代码执行顺序拆解
- 执行
this.showBlock = true,触发响应式更新逻辑,但此时DOM并未立即创建,更新请求被暂存到异步队列中。 - 同步调用
changePosition方法,此时当前同步代码还在执行,Vue的异步队列还没处理,this.$refs.blob对应的DOM元素还未挂载,因此返回undefined。 setTimeout的回调会被加入宏任务队列,而Vue的异步更新队列属于微任务。根据浏览器事件循环规则,微任务会在当前同步代码执行完后优先执行,完成DOM更新后,才会执行宏任务队列中的setTimeout回调,这时$refs.blob已经存在,就能正常获取到DOM元素。
为什么1ms延迟也能生效?
这和1ms的时长无关,哪怕设置setTimeout(fn, 0)也会得到同样结果。因为setTimeout的回调会被推到下一个事件循环周期执行,此时Vue已经完成了DOM更新操作,所以能拿到对应的元素。
正确的解决方案:使用$nextTick
如果需要在数据更新后立即操作DOM,推荐使用Vue提供的this.$nextTick方法,它会在Vue完成DOM更新后立即执行回调,比setTimeout更可靠,不需要依赖事件循环的宏任务:
methods: { changePosition() { this.$nextTick(() => { console.log(this.$refs.blob); // 正常获取DOM元素 }) }, }
内容的提问来源于stack exchange,提问作者happy_story
相关产品推荐
相关产品推荐

