Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[vue] 你知道nextTick的原理吗? #363

Open
haizhilin2013 opened this issue Jun 20, 2019 · 3 comments
Open

[vue] 你知道nextTick的原理吗? #363

haizhilin2013 opened this issue Jun 20, 2019 · 3 comments
Labels
vue vue

Comments

@haizhilin2013
Copy link
Collaborator

[vue] 你知道nextTick的原理吗?

@haizhilin2013 haizhilin2013 added the vue vue label Jun 20, 2019
@persist-xyz
Copy link

persist-xyz commented Jul 3, 2019

用法:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

Vue官网
提到DOM的更新是异步执行的,只要数据发生变化,将会开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。

简单来说,就是当数据发生变化时,视图不会立即更新,而是等到同一事件循环中所有数据变化完成之后,再统一更新视图。

关于异步的解析,可以查看阮一峰老师的这篇文章,具体来说,异步执行的运行机制如下。

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。

(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。

(4)主线程不断重复上面的第三步。

例子:

//改变数据
vm.message = 'changed'

//想要立即使用更新后的DOM。这样不行,因为设置message后DOM还没有更新
console.log(vm.$el.textContent) // 并不会得到'changed'

//这样可以,nextTick里面的代码会在DOM更新后执行
Vue.nextTick(function(){
    console.log(vm.$el.textContent) //可以得到'changed'
})

那么,Vue内部是如何实现的呢?

可以了解一下哇 NextTick - 源码版 之 独立自身

@Myh-cs
Copy link

Myh-cs commented Jul 9, 2019

微任务与宏任务吧 ,完了根据浏览器的支持情况 promise setImmediate setTimeout 做退化

@ZihaoChoi
Copy link

vue更新DOM是异步操作,等所有数据更新后才会渲染DOM。所以要在更新DOM会操作,vue提供了nextTick。nextTick方法在源码内会通过各种方法检测DOM是否更新完成。如果有promise.then就用promise监听,没有就降级成MutationObserver,还不支持就降级setImmediate,都不支持就用setTimeout

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
vue vue
Projects
None yet
Development

No branches or pull requests

4 participants