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有什么作用? #268

Open
haizhilin2013 opened this issue Jun 16, 2019 · 8 comments
Open

[vue] $nextTick有什么作用? #268

haizhilin2013 opened this issue Jun 16, 2019 · 8 comments
Labels
vue vue

Comments

@haizhilin2013
Copy link
Collaborator

[vue] $nextTick有什么作用?

@haizhilin2013 haizhilin2013 added the vue vue label Jun 16, 2019
@wenyejie
Copy link

在队列中插入一个回调, 当前面的dom操作, 其它回调执行完成之后, 执行当前callback
这样做的好处是, 我前面用到的一些dom更新等已经处理完毕, 而不是获取到更新前的数据

// e.g
// do something
console.log(this.$refs.message) // old dom

this.$nextTick()
  .then(() => {
    console.log(this.$refs.message) // new dom
  })

@Zjingbo
Copy link

Zjingbo commented Jul 2, 2019

处理数据动态变化后,dom还未及时更新的问题。nexttick就可以获取到数据更新后最新的dom变化

@MontageD
Copy link

文档中特别提到了两个词,

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

「DOM更新循环结束后之后」「在修改数据之后」也就是说它触发的时机实在dom 更新完毕以及动态数据触发双向绑定的虚拟dom 渲染结束之后才会产生的回调..

@chen0821
Copy link

vue响应式的改变一个值以后,此时的dom并不会立即更新,如果需要在数据改变以后立即通过dom做一些操作,可以使用$nextTick获得更新后的dom。

@dealdot
Copy link

dealdot commented Apr 9, 2021

就像react 的setState()函数一样,它是异步的,调用完后立即打印state是没有变化的,同理vue中当data有变化时,dom将会更新,但这时如果你紧接着直接操作dom是不行的,因为dom更新是异步的,js是单线程,dom操作这些费时的东西一定会放到异步队列中,等主线程的代码执行完再执行异步代码,dom更新后会有个回调通知,这时异步代码算是执行完了,dom也更新了,$nextTrick(fun)里的fun就是异步回调,在这里操作可以保证dom已经更新完毕

@hyj443
Copy link

hyj443 commented Oct 21, 2021

如果用户想在数据变化后操作到最新的DOM,那么在同步代码中是获取不到最新DOM的,因为DOM还没重新渲染,为什么还没重新渲染,待会会详细说明。

$nextTick就是解决这个问题的api,我们在修改数据后,调用$nextTick,将操作最新DOM的代码写在回调中,回调会延迟到下次DOM更新循环后执行,这样操作的肯定是更新后的DOM

然后$nextTick是对nextTick的封装,nextTick函数不单止用在这里,还用在nextTick(flushQueueWatcher)

这是什么,是将更新DOM的回调推入callbacks数组中,nextTick(flushQueueWatcher)是在queueWatcher时调用的,修改数据时,update函数被触发,就会queueWatcher,然后你接着$nextTick(fn),这样 callbacks数组中,更新DOM的回调就在fn之前,就会先被执行。

当同步代码都执行完了,会去检查微任务队列中是否有事件存在,如果存在,则会依次执行微任务队列中事件对应的回调,直到微任务队列清空,然后去宏任务队列中取出一个事件,把对应的回调加入当前执行栈,当执行栈中所有任务执行完毕后,再次检查微任务队列中是否有事件存在,无限重复这个过程,叫浏览器的事件循环。

两个不同的宏任务之间穿插着UI的重渲染,那么我们只需在微任务中把所有需要更新的数据更新,即执行 flushCallbacks ,情况Callbacks数组中的回调,开头是flushQueueWatcher,作用是执行并清空queue中的watcher的run方法,对表达式或渲染函数重新求值,生成最新的DOM,然后才是用户通过$nextTick注册的回调,这些回调就可以操作到最新的DOM。微任务结束后,执行宏任务,即浏览器将最新的DOM渲染到页面,所以只需要一次UI重渲染就能得到最新的DOM。

@yxllovewq
Copy link

举一个简单的例子就知道了,在created勾子中修改数据的值后,无法马上获取更新后的DOM,只能到updated勾子触发,在updated的勾子中获取。如果想在created中获取更新后的DOM,可以借助$nextTick

@Cai-zhiji
Copy link

在Vue中,$nextTick 是一个实例方法,用于在下次DOM更新循环结束之后执行延迟回调。它的主要作用有以下几个方面:

获取更新后的DOM状态:

当你修改了Vue实例中的数据,Vue会异步执行DOM更新。使用 $nextTick 可以在DOM更新完成后获取到更新后的DOM状态,以便进行进一步的操作。

确保DOM更新完毕后的回调执行:

有时候,你可能需要在Vue更新DOM后执行一些操作,例如访问动态计算后的样式或操作更新后的DOM元素。使用 $nextTick 可以确保在DOM更新完成后执行回调函数。

异步更新数据后的回调:

当你使用 vm.$set 或 vm.$delete 修改响应式数据时,数据的变化可能不会立即生效。使用 $nextTick 可以在数据更新生效后执行回调函数。

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="updateMessage">Update Message</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  methods: {
    updateMessage() {
      this.message = 'Updated Message';
      this.$nextTick(() => {
        // DOM更新后执行的回调
        console.log('DOM updated');
        // 可以访问更新后的DOM状态或进行其他操作
        const pElement = document.querySelector('p');
        console.log('Updated message:', pElement.textContent);
      });
    }
  }
};
</script>

在上述示例中,当点击按钮时,updateMessage 方法会将 message 数据更新为 'Updated Message'。然后,通过 $nextTick 方法,在DOM更新完成后执行回调函数。在回调函数中,我们可以访问更新后的DOM状态,例如获取更新后的文本内容。

总结来说,$nextTick 方法用于在下次DOM更新循环结束后执行回调函数,可以获取更新后的DOM状态,确保在DOM更新完成后执行操作,以及处理异步更新数据后的回调。

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

9 participants