您当前的位置: 首页 > 

@大迁世界

暂无认证

  • 0浏览

    0关注

    739博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【思考】$nextTick 与 setTimeout 的一点对比!

@大迁世界 发布时间:2021-07-14 08:27:01 ,浏览量:0

作者:Chimezie Enyinnaya 译者:前端小智 来源:blog

有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。

一个前端开发人员(小智)走进了一个Vue酒吧。小智点了他最喜欢的鸡尾酒:Nuxt。酒保正在努力制作中。然后他自己就唠叨了起来。

小智讲述了他是如何在Vue 3的实例方法下发现$nextTick的,并大吃一惊。小智 使用Vue已经有一段时间了,他已经习惯了把$watch$emit写成实例方法。那么,$nextTick是用来做什么的?Vue文档说,它"[defers]回调,在下一个DOM更新周期后执行"。

但是小智并不相信。

他继续讲述他是如何尝试这样做的:

this.loadingAnimation = true
this.startVeryLongCalculation()
this.completeVeryLongCalculation()
this.loadingAnimation = false

有用。 为什么?

nextTick做什么?

nextTick接受一个延迟到下一个DOM更新周期的回调函数。这只是Vue的一种说法,“嘿,如果你想在DOM更新后执行一个函数(这种情况很少发生),我希望你使用nextTick而不是setTimeout”。

Vue.nextTick(() => {}) // syntax

下面很快就会讲到setTimeoutnextTick参数。我们用这个例子来可视化nextTick的行为:


  
{{ currentTime }}
export default { name: 'getCurrentTime', data() { return { currentTime: '' } }, mounted() { this.currentTime = 3; this.$nextTick(() => { let date = new Date() this.currentTime = date.getFullYear() }); } }

在J电脑上运行这个代码片段。它将显示2021年。并不是说如果你去掉nextTick,就不会得到同样的结果。然而,你应该明白,Vue会根据数据中的内容对DOM进行修改。

在上面的代码片段中,Vue将DOM更新为3,然后调用回调,将DOM更新为2021,最后将控制权交给浏览器,浏览器将显示2021

到目前为止,我们已经研究了nextTick在回调队列中插入回调函数并在适当的时候执行该函数。

这个你可能会感兴趣,nextTick中的回调是作为事件循环中的一个微任务使用的。nextTick的源代码明确指出,“nextTick行为利用了微任务队列,可以通过本地的Promise.thenMutationObserver来访问。”

setTimeout vs nextTick

在DOM更新后执行函数的另一种方法是使用JavaScript的setTimeout()函数。

我们将上面的代码用setTimeout替换nextTick:


  
{{ currentTime }}
export default { name: 'getCurrentTime', data() { return { currentTime: '' } }, mounted() { this.currentTime = 3; setTimeout(() => { let date = new Date() this.currentTime = date.getFullYear() }, 0); } }

运行此代码片段。 首先看到3然后2021。它发生得很快,因此如果没有看到此行为,需要刷新浏览器。

在上面的代码片段中,Vue将DOM更新为3,并提供浏览器控制。然后浏览器显示3,调用回调函数,将DOM更新到2021,最后将控制权交给浏览器,现在浏览器显示2021

nextTick的实现在不支持PromiseMutationObserver的浏览器(IE 6-10和Opera Mini浏览器)上,使用setTimeout作为后备方法,对于不支持PromiseMutationObserver的浏览器(IE 10),它更倾向于setImmediate

何时使用 nexttick
  • 当你想使用setTimeout
  • 当你想确定DOM能反映你的数据时
  • 在尝试执行异步操作时,遇到Uncaught (in promise) DOMException等错误。记住,Vue是异步更新DOM的

最后来个示例:

  • {{month}}
Add Month
Vue.createApp({ data() { return { month: '', months: ['Jan', 'Feb', 'Apr', 'May', 'June', 'July', 'Aug'] } }, mounted() { this.updateScrollNextTick() }, methods: { addMessage() { if(this.month == ''){ return } this.months.push(this.month) this.month = '' this.updateScrollNextTick() }, updateScrollNextTick () { let scrolledHeight = this.$refs.scrolledHeight.clientHeight this.$nextTick(() => { this.$refs.listScroll.scrollTo({ behavior: 'smooth', top: scrolledHeight }) }) } }, }) .mount("#app")

示例地址:https://codepen.io/ammezie/pen/OJpOvQE

主要部分:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oXrfxVSW-1626221844061)(/img/bVcS117)]

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zH0NCUvs-1626221844063)(/img/bVcS119)]

在上面的代码片断中,我们想在一个新项目被添加到列表中时获得平滑的向下滚动效果。浏览一下代码,尝试修改一下,去掉nextTick,你就会失去那种平滑的滚动效果。你也可以尝试用setTimeout来代替nextTick

总结

在本文中,我们探索了nextTick是如何工作的。我们进一步了解了它与普通的JavaScript setTimeout的不同之处,并介绍了实际的用例。

~完,我是小智,准备去教育一个前端小妹。

编辑中可能存在的bug没法实时知道,事后为了解决这些bug,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。

原文:https://blog.logrocket.com/understanding-nexttick-in-vue-js/

交流

文章每周持续更新,可以微信搜索**【大迁世界 】第一时间阅读,回复【福利】**有多份前端视频等着你,本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,欢迎Star。

关注
打赏
1664287990
查看更多评论
立即登录/注册

微信扫码登录

0.0375s