Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
–
–
–
It's all about Timing
nextTick
allows you to execute code
after
you have changed some data and Vue.js has updated the virtual DOM based on your data change, but
before
the browser has rendered that change on the page.
Normally,
devs use the native JavaScript function
setTimeout
to achieve similar behavior, but using
setTimeout
relinquishes control over to the browser
before
it gives control back to you (via calling your callback).
Example
Let's say you changed some data; Vue then updates the vDOM based on that data change (the changes are not yet rendered to the screen by the browser).
If you used
nextTick
at this point, your callback would get called immediately, and the browser would update the page after that callback finished executing.
If you instead used
setTimeout
, then the browser would have a chance to update the page, and
then
your callback would get called.
You can visualize this behavior by creating a small component like the following:
(Check
this fiddle
to see it live)
<template>
<div class="hello">
{{ msg }}
</template>
<script>
export default {
name: 'HelloWorld',
data() {
return {
msg: 'One'
mounted() {
this.msg = 'Two';
this.$nextTick(() => {
this.msg = 'Three';
</script>
Run your local server. You will see the message "Three" being displayed.
Now, replace this.$nextTick
with setTimeout
:
setTimeout(() => {
this.msg = 'Three';
}, 0);
Reload the browser. You will see "Two" before you see "Three".
That's because, with setTimeout
:
Vue updated the vDOM to say "Two"
Vue gave control to the browser
The browser displayed "Two"
Callback was called
Vue updated the vDOM to say "Three"
Vue gave control to the browser
The browser displayed "Three"
But with nextTick
, we skip steps 2 and 3! Instead of passing over control after the first vDOM update, Vue calls the callback immediately, which prevents the browser from updating until the callback is finished. In this example, that means "Two" is never actually displayed.
To understand how Vue implements this, you need to understand the concept of the JavaScript Event Loop and microtasks.
Once you have those concepts clear(er), check the source code for nextTick.
–
Next Tick basically allows you to run some code, after the vue has re-rendered the component when you have made some changes to the a reactive property (data).
// modify data
vm.msg = 'Hello'
// DOM not updated yet
Vue.nextTick(function () {
// this function is called when vue has re-rendered the component.
// usage as a promise (2.1.0+, see note below)
Vue.nextTick()
.then(function () {
// this function is called when vue has re-rendered the component.
From the Vue.js Documentation:
Defer the callback to be executed after the next DOM update cycle. Use it immediately after you’ve changed some data to wait for the DOM update.
Read more about it, here.
–
–
–
To make Pranshat's answer about the difference between using nextTick
and setTimeout
, more explicit, I have forked his fiddle:
mounted() {
this.one = "One";
setTimeout(() => {
this.two = "Two"
}, 0);
//this.$nextTick(()=>{
// this.two = "Two"
//})}
You can see in the fiddle that when using setTimeOut
, the initial data flashes very briefly once the component gets mounted before adapting the change. Whereas, when using nextTick
, the data is hijacked, changed, before rendering to the browser. So, the browser shows the updated data without even any knowledge of the old.
Hope that clears the two concepts in one swoop.
<div id="app">
<div ref="scrolledList" style="height: 100px; width: 150px; border:1px solid red; overflow: auto; margin-bottom: 15px; padding: 5px;">
<ul ref="scrolledHeight" style="margin: 0; padding: 0;">
<li v-for="msg in messages">
{{msg}}
<input type="text" placeholder="Add Message" v-model="message" />
<button @click="addMessage" @keyup.enter="addMessage"> Add Message</button>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data() {
return {
message: '',
messages: [1,2,3,4,5,6,7,8,9,10]
mounted() {
this.updateScrollNextTick()
methods: {
addMessage() {
if(this.message == ''){
return
this.messages.push(this.message)
this.message = ""
this.updateScrollNextTick()
updateScrollNextTick () {
this.$nextTick( () => {
let scrolledHeight = this.$refs.scrolledHeight.clientHeight
this.$refs.scrolledList.scrollTo({
behavior: 'smooth',
top: scrolledHeight
.mount("#app")
</script>
</body>
</html>
1-nextTick() comes at first render of page, and every other
Re-render after that. onUpdated() wont call on first Render but
every Re-render after that (every update).
2- nextTick() comes before onUpdated() and also before
onBeforeUpdate()
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.