vue 之 $nextTick
官方说明:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM
疑问:
- DOM 更新循环是指什么?
- 下次更新循环是什么时候?
- 修改数据之后使用,是加快了数据更新进度吗?
- 在什么情况下要用到?
原理
vue的响应式并不是数据发生变化之后DOM立即变化,而是按照一定的方式进行DOM的更新
第一个案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <template> <div id= "app" > <input type= "text" ref = "ipt" v- if = "isShow" /> <button @click= "fn" v- else >点击修改</button> </div> </template> <script> export default { name: "App" , data() { return { isShow: false , }; }, methods: { fn() { this .isShow = true ; console.log( this .$refs.ipt); // undefined this.$refs.ipt.focus() //报错 }, }, }; </script> <style></style> |
遇到上述情况怎么解决呢?
1 2 3 | this .isShow = true ; setTimeout(() => { console.log( this .$refs.ipt); //<input type="text"><br> this.$refs.ipt.focus()}, 0); <br>//或者 <br>this.$nextTick(() => { <br> console.log(this.$refs.ipt); //<input type="text"><br> this.$refs.ipt.focus()}); |
分析:因为 this.isShow = true;时,虚拟dom需要通过diff算法进行更新,这个过程是需要时间的,而同步的代码中,this.$refs.ipt 所需时间 小于 这个渲染时间
第二个案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <template> <section> <h1 ref = "hello" >{{ value }}</h1> <el-button type= "danger" @click= "get" >点击</el-button> </section> </template> <script> export default { data() { return { value: 'Hello World ~' }; }, methods: { get () { this .value = '你好啊' ; console.log( this .$refs[ 'hello' ].innerText); // Hello World ~ this .$nextTick(() => { console.log( this .$refs[ 'hello' ].innerText); // 你好啊 }); } }, mounted() { }, created() { } } </script> |
应用场景:
需要在视图更新之后,基于新的视图进行操作
思考的问题:$nextTick 如何 结合 created 和 mounted 来处理问题
疑问:
疑问一 . this.$nextTick 为什么要放在 created 或者 mounted ,有什么区别
疑问二 . 为什么$nextTick能保证子组件都加载完?
第一步:了解 created
1 2 3 4 5 6 | //组件创建之后 created() { // 可以操作数据,发送ajax请求,并且可以实现 // vue对页面的影响 应用:发送ajax请求 console.log( '组件创建后:' + this .msg); //哈哈哈 } |
第二步:了解mounted
1 2 3 4 5 | //装载数据到DOM之后 mounted() { // 可以操作DOM console.log( 'DOM装载后:' +document.getElementById( 'app' )); //<div id="app"><div id="test"></div></div> } |
第三步:分析
疑问一
1.例如在parent 里面有 两个child组件,但是父组件通过异步获取的数据data(created),data里面有childData1 和 childData2 那么此时通过this.$refs.child1是获取不到的,所以需要用到 this.$nextTick,这样可以解决刚才的案例问题(但是,若是同步的组件,那么在parent里面的 mounted 获取 this.$refs.child1也是可以的,那么就不需要该死的this.$nextTick)
2.将this.$nextTict 写在 created 和 mounted 没太大的区别,只是created 会优先 mounted执行,参考 vue 之 生命周期(钩子)
疑问二
如果是同步子组件,mounted
就已经能保证了同步子组件都加载完了。因为对于一个页面来说,第一次 DOM 更新循环结束,也就是 mounted
的时候。
同步顺序是 parent created
→ child created
→ child mounted
→ child $nextTick
→ parent mounted
→ parent $nextTick
。
如果是异步子组件,你需要在 mounted
里写 $nextTick
,但也并不能完全保证子组件加载完毕,因为异步子组件里还可以再套异步孙子组件。
总而言之,同步子组件,写 created
+ $nextTick
和写 mounted
都行;异步子组件,除非是在父组件中直接操作异步子组件的生命周期钩子、或者子组件通过 $emit
的方式通知父组件,否则单纯靠父组件自己,是无法百分百保证的。
参考:http://errornoerror.com/question/10048646268771205890/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现