问题描述:

在mounted中打印this.$refs时可以获取到数据
在这里插入图片描述

但打印this.$refs.text1时,则获取不到数据,显示undefined

在这里插入图片描述


后续:通过使用this.$nextTick后有些场景可获取到数据,但有些场景依旧获取不到数据,还是显示undefined

原因分析:

mounted 阶段是加载阶段,有些DOM可能存在还没有完成的情况。


搜索到的解释:

当使用$nextTick时,将在微任务(不支持微任务的浏览器将回退至宏任务)堆栈中入栈写的回调。如果所有子组件都已经下载完毕,并在Vue中定义,则从根组件往后渲染时,因为用的都是同步方法,微任务将在这些同步方法后被执行,所以大多数时候可以通过$nextTick获取子组件渲染后的DOM节点。但是如果实例化组件的时候,有其他微任务入栈,就要看微任务队列的执行顺序了,所以无法完全保证。对于异步组件,由于网络原因,import微任务总在$nextTick之后,所以总是拿不到子组件的DOM。
个人的一些理解:
1、当要获取的数据是异步获取时,mounted执行的时候,数据还未被获取到,$nextTick的触发在数据异步获取之前?
2、使用了v-ifv-forv-show这些指令时,会根据不同的条件去动态的渲染DOM树,此时DOM在mounted阶段是不存在的;

解决方案:

通过查询资料,因为ref本身是作为渲染结果被创建的,在渲染的时候是不能访问的,因为他们还不存在。$refs不是响应式的,只在组件渲染完成后才填充”,所以可以在DOM渲染完毕后再进行获取。和this.$nextTick结合使用,nextTick 是在下次DOM更新循环结束之后执行延迟回调,在修改数据之后使用$nextTick,则可以在回调中获取更新后的 DOM。


this.$nextTick外面再用一个setTimeout,由于setTimeout是宏任务,所以一般会在渲染后执行。但对于异步组件,如果由于网络延迟,导致微任务在宏任务之后入栈,则在setTimeout的回调中仍无法获取子组件的DOM。简单的来说,由于有异步执行顺序的影响,只能保证单独组件内部的执行顺序,无法保证其他组件的解析注册执行顺序。


总结:

当遇到该问题时,可先添加this.$nextTick来解决,如果无法解决,可在this.$nextTick使用setTimeoutpromise等异步来解决。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐